reso.js
is a Node.js
client for interacting with RESO Web API services, fully aligned with the current RESO Web API specification.
It includes features like custom request/response hooks, automatic authentication token refresh, and built-in rate limiting.
Install with your preferred package manager:
pnpm add reso.js
# or
npm install reso.js
# or
yarn add reso.js
This library works with any RESO-compliant server following the RESO Web API spec. Additionally, it provides official support for:
reso.js
supports both Bearer Token and Client Credentials authentication strategies. Refer to your feed's documentation for your feeds supported strategy and how to obtain credentials.
import { createFeed } from 'reso.js';
const feed = createFeed({
http: {
baseURL: 'http://my-reso-api.com',
},
auth: {
type: 'token',
credentials: {
token: 'MY_TOKEN',
},
},
});
The bearer token provided must not expire.
import { createFeed } from 'reso.js';
const feed = createFeed({
http: {
baseURL: 'http://my-reso-api.com',
},
auth: {
type: 'credentials',
credentials :{
tokenURL: 'http://my-reso-api.com/token'
clientId: 'MY_CLIENT_ID'
clientSecret: 'MY_CLIENT_SECRET'
}
},
});
You can optionally include grantType
and scope
. Tokens will automatically refresh 30 seconds before expiry by default.
To custom the refresh buffer it can be passed in the with the auth strategy:
import { createFeed } from 'reso.js';
const feed = createFeed({
http: {
baseURL: 'http://my-reso-api.com',
},
auth: {
type: 'credentials',
credentials :{
tokenURL: 'http://my-reso-api.com/token'
clientId: 'MY_CLIENT_ID'
clientSecret: 'MY_CLIENT_SECRET'
},
refreshBuffer:40000,
},
});
Perform a RESO-compliant query. The function is an async generator that will auto paginate any next pages if the nextLink is present every time .next()
is called or the result is looped over.
for await (let properties of feed.readByQuery('Property', '$filter=ListPrice gt 100000')) {
for (property of properties.values) {
console.log(property);
}
}
Retrieve a specific record by ID:
const myProperty = await feed.readyById('Property', 123);
console.log(myProperty.value);
Get the feed’s metadata XML:
const metadata = await feed.$metadata();
console.log(metadata);
Rate limiting is built-in for supported providers. You can also customize limits:
const feed = createFeed({
http: {
baseURL: 'http://my-reso-api.com',
},
limiter: {
duration: 30000, // 30 seconds
points: 5, // max 5 requests per duration
},
});
duration
defines the time window in milliseconds, andpoints
sets the maximum number of requests allowed within that window.
The clients behaviour can be customized with the following supported hooks:
onRequest
onRequestError
onResponse
onResponseError
These are backed by ofetch interceptors. Additional hooks will be added/supported as needed.
Example – Appending /replication
to Property
requests:
hooks: {
onRequest: [
({ request }) => {
if (request.toLowerCase().includes('property')) {
request += '/replication';
}
},
],
},
The client throws a FeedError
with detailed RESO error info:
try {
const myProperty = await feed.readById('Property', 123);
console.log(myProperty.value);
} catch (error) {
if (error instanceof FeedError) {
console.log(error.details);
}
}
Bug reports, pull requests and feature discussions are welcome on GitHub