npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@smartretraining/rex-effect

v0.2.0

Published

Effect-native SDK for the Rex Software real-estate API, generated from Rex's describe/describeModel introspection.

Readme

@smartretraining/rex-effect

Effect-native SDK for the Rex Software real-estate API.

Rex ships no static OpenAPI document — it self-describes through introspection endpoints. This package scrapes that introspection, transforms it into a standard OpenAPI 3.1 document, and generates Effect operations from it with the same generator used by the other @distilled.cloud/* SDKs.

Installation

npm install @smartretraining/rex-effect effect

Quick Start

import { Effect, Layer } from "effect";
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
import { CredentialsFromEnv } from "@smartretraining/rex-effect";
import { ListingsSearch } from "@smartretraining/rex-effect";

const RexLive = Layer.merge(FetchHttpClient.layer, CredentialsFromEnv);

const program = Effect.gen(function* () {
  const page = yield* ListingsSearch({ limit: 10 });
  return page.rows ?? [];
});

const rows = await Effect.runPromise(program.pipe(Effect.provide(RexLive)));

Every operation is a function Op(input) => Effect<Output, Error, ...>. The Rex { result, error, correlation } envelope is unwrapped automatically by the client — generated output schemas describe just the inner result payload.

Single-import, tree-shakeable client

For one import that exposes every operation, use a namespace import. Bundlers statically analyse namespace member access, so only the operations you actually call are kept:

import * as rex from "@smartretraining/rex-effect/Operations";

rex.ListingsSearch({ limit: 10 });
rex.PropertiesCreate({ /* ... */ });

import * as rex from "@smartretraining/rex-effect" works too — same operations, plus Category, Retry, the error types, and credentials helpers.

Configuration

Rex uses session-token auth, not a static API key. Provide credentials one of three ways:

# Option A — you already hold a session token
REX_API_TOKEN=your-session-token

# Option B — email + password; the SDK performs the login exchange
[email protected]
REX_PASSWORD=your-password

# Optional — override the API origin (defaults to https://api.rexsoftware.com)
REX_API_BASE_URL=https://api.rexsoftware.com
  • CredentialsFromEnv — reads the variables above (prefers REX_API_TOKEN).
  • CredentialsFromToken(token, { apiBaseUrl? }) — build a layer from a token.
  • Construct the Credentials service directly.

Receiving webhooks

The generated AdminWebhooks* operations manage webhook subscriptions (create, update, search, markAsHealthy, etc.). Decoding the inbound HTTP POST body Rex sends to your callback URL is a separate concern — Rex's introspection has no schema for it, so the delivery payload is hand-modelled in @smartretraining/rex-effect/Webhooks.

import { Effect } from "effect";
import { decodeWebhookDelivery } from "@smartretraining/rex-effect";

// inside your HTTP handler:
const delivery = yield* decodeWebhookDelivery(await req.json());

for (const event of delivery.data) {
  if (event.payload.format === "v1_full_change_detail") {
    event.payload.data.post; // current record state
    event.payload.data.pre;  // previous state, or null on "create" events
  } else {
    // v1_context_only — fetch the record yourself
    const { service, record_id } = event.payload.context;
  }
}

decodeWebhookDelivery fails with RexParseError if the body doesn't match. The payload is a discriminated union on payload.format (v1_full_change_detail vs v1_context_only), so narrowing on it gives you fully-typed access to either shape.

See docs/admin-webhooks.md for a full Effect-based sync handler on Cloudflare Workers — subscribe, a fast-ack fetch delivery handler (ctx.waitUntil), a scheduled nightly e-tag backstop (Cron Trigger), and unhealthy-webhook recovery — following Rex's recommended approach.

Regenerating the SDK

Operations in src/operations/ are generated. To regenerate or extend them:

1. Scrape Rex introspection

bun run specs:scrape

Requires REX_API_TOKEN, or REX_EMAIL + REX_PASSWORD, in the environment. Writes specs/rex/{Service}.describe.json, specs/rex/{Service}.describeModel.json, and specs/rex/_catalog.json.

2. Generate

bun run generate

This chains three steps:

  1. scripts/build-openapi.ts — transforms the scraped specs/rex/*.describe.json files into a single OpenAPI 3.1 document at specs/openapi.generated.json.
  2. scripts/generate.ts — runs the shared @distilled.cloud/core OpenAPI generator over that document, emitting one module per Rex method into src/operations/ and rewriting the index.ts barrel.
  3. oxlint --fix + oxfmt — lint and format the generated code.

Re-running bun run generate with unchanged specs is idempotent.

Adding more Rex services

Rex has ~272 services. This package generates Listings, Properties, and AdminWebhooks. To add another:

  1. Append the service name to the SERVICES array in scripts/scrape-specs.ts.
  2. Run bun run specs:scrape then bun run generate.

build-openapi.ts globs every specs/rex/*.describe.json file, so new services flow through automatically. Note: removing a service does not delete its stale src/operations/*.ts files — prune those by hand.

Known limitations

  • Output schemas are inferred from the example records embedded in Rex's describe payloads. Methods that ship no example get a permissive schema. Every inferred field is treated as nullable, since one example can't prove a field is never null.
  • search.criteria is an opaque object in Rex's openapi block. The real query surface lives in {Service}.describeModel.json (searchable_fields) and is not yet folded into the generated input schemas.
  • Rex returns logical failures as HTTP 200 with a non-null envelope error. These surface as a RexApiError defect rather than a typed error channel — see the note in src/client.ts.

License

MIT