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/vaultre-effect

v0.10.0

Published

Effect-native SDK for the VaultRE API, generated from the vendor's published OpenAPI document.

Downloads

236

Readme

@smartretraining/vaultre-effect

Effect-native SDK for the VaultRE API (v1.3), generated from the vendor's own published OpenAPI document.

import * as Effect from "effect/Effect";
import * as Stream from "effect/Stream";
import * as Vaultre from "@smartretraining/vaultre-effect";
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";

const listings = Stream.runCollect(
  Vaultre.getPropertiesLifeSale.items({ status: ["listing"], pagesize: 50 }),
).pipe(
  Effect.provide(
    Vaultre.fromApiKey({
      apiKey: process.env.VAULTRE_API_KEY!,
      accessToken: process.env.VAULTRE_ACCESS_TOKEN!,
    }),
  ),
  Effect.provide(FetchHttpClient.layer),
  Vaultre.Retry.throttling,
);

453 operations. 146 of them paginate.

What is verified, and what is not

The document is the vendor's, and it is a good one. VaultRE publishes Swagger UI over vaultre.yaml, mirrored verbatim at specs/vaultre.yaml. It is OpenAPI 3.0.1, it declares exactly one server — the same origin this SDK defaults to — and it holds together where vendor documents usually do not: 338 of its 356 component schemas are reachable from a path, every operation carries a unique operationId, and 421 of 453 declare a typed JSON body. Nothing had to be transcribed or repaired to build this package.

No request in it has ever been made. VaultRE issues keys to registered integrators only, so every response schema here is the document's claim rather than an observation.

Unlike ../boxdice, the schemas are not deliberately widened. There is nothing to widen: core emits every enum as S.String and every optional member as optional (codegen/emit.ts), so an undocumented status or an absent field already passes through at runtime. The enums are a compile-time hint, and a value outside one is typed narrower than it is rather than rejected. The document is passed through untouched — including where it contradicts itself, which is listed below.

Getting to verified

test/live.test.ts is the day-one checklist, already written. It skips itself without credentials:

echo 'VAULTRE_API_KEY=…'      >> .env
echo 'VAULTRE_ACCESS_TOKEN=…' >> .env
bun run test

If the response side turns out to need repair rather than confirmation, copy ../reapit/scripts/capture-samples.ts — it records response structure only, no values, so its output is safe to commit — and merge it over the document the way ../reapit/scripts/build-spec.ts does.

Check these first

| Doubt | Why it matters | | --- | --- | | status is declared four ways | 9 values on a property, 9 on LinkedProperty, 8 on SaleHistory (no management), and a 7-value ?status= filter that includes listingOrConditional and excludes settled. At most one describes a real tenant. | | pagesize has no documented maximum | It defaults to 50. A caller asking for 500 may quietly get 50 — count items, never assume. | | The error body | SuccessOrError ({ success, msg, code }) covers 155 of the 177 declared 400s. DELETE /properties/{id}/photos answers something else entirely, so the shape is not universal. | | 401 vs 403 on a scope failure | Scopes are granted per access token by the customer, so an operation can work for one agency and fail for another. Which status that is decides whether it retries. | | The 32 operations with no declared JSON body | Mostly file and photo endpoints. They generate as Unit; if one of them actually returns JSON, it is being thrown away. |

Things the API does that will surprise you

Two secrets, owned by two different parties. X-Api-Key is the integrator's, issued once to the software. Authorization: Bearer is the agency's, issued per account with the scopes that agency granted. Both go on every request; one process syncing many agencies holds one key and many tokens.

A property is not a listing. A property record persists across every time it goes to market, and each campaign is a life: saleLifeId and leaseLifeId on the property point at them. Everything about a sale — purchasers, owners, solicitors, offer conditions, portals, feedback — hangs off /properties/{id}/sale/{lifeid}/…, not off the property.

Two path segments are vocabulary, not ids. /properties/{class}/{salelease}/… takes residential|commercial|business|rural|land|holidayRental and sale|lease. They are path labels; the SDK types them as open unions.

The page envelope is not proof of pagination. Twelve operations return { items, totalItems, totalPages } while accepting no page parameter — /user/teams and /properties/{id}/{salelease}/{lifeid}/hazards among them. They are complete lists wearing the envelope, and .pages/.items are deliberately not generated for them (scripts/generate.ts).

Nothing in a page says which page it is. There is no current, and urls.next is a fully-formed URL rather than a token. src/pagination.ts counts its own pages and stops on totalPages.

The quota is daily and it does not clear by waiting. 10 requests/second and 10,000/day per key, resetting at 00:00 UTC, both answered with 429. Retry.throttling recovers a burst; nothing recovers the day's quota, so watch getUsage rather than the 429.

Push exists. VaultRE sends signed webhooks (X-VaultRE-Signature: t=<ms>,sha512=<hmac> over the timestamp, a period and the raw body, keyed with the API key) and also offers GET /eventStream for polling. The published event catalogue names only property.update and user.update; the rest has to come from VaultRE. Neither is wired up here.

Layout

specs/vaultre.yaml        vendor OpenAPI document, mirrored verbatim
scripts/fetch-spec.ts     re-download it; the diff IS the vendor's change
scripts/convert.ts        openapi → .generated-specs/vaultre.json (smithy)
scripts/generate.ts       smithy → src/services/vaultre.ts
src/*.ts                  hand-written: credentials, protocol, errors,
                          pagination, retry, traits
test/                     offline: protocol, pagination, spec translation
test/live.test.ts         skipped until credentials exist
bun run specs:fetch   # only when checking for vendor drift
bun run convert && bun run generate && bun run typecheck && bun run test

Credentials

Vaultre.fromApiKey({ apiKey, accessToken })              // one agency
Vaultre.fromApiKey({ apiKey, accessToken, apiBaseUrl })  // another region, if one appears
Vaultre.CredentialsFromEnv                               // VAULTRE_API_KEY + VAULTRE_ACCESS_TOKEN

The base URL carries the API version (…/api/v1.3) and the schemas in this package were generated from the v1.3 document, so pointing it at v1.2 would compile and then lie.

Releasing

The @smartretraining packages share a single version line and ship together from .github/workflows/release-smartretraining.yml, which refuses to run if they disagree on the version or if it is already on the registry. That is why this package has no 0.1.0 — it joins rex-effect, reapit-effect and boxdice-effect on their existing line, at 0.9.0.