featurable
v0.1.0
Published
Node.js and TypeScript SDK for the Featurable API.
Maintainers
Readme
featurable
Node.js and TypeScript SDK for the Featurable API.
Fetch your Featurable widgets and their Google reviews from any Node.js or TypeScript application. Written in TypeScript with full type definitions, zero runtime dependencies, and both ESM and CommonJS builds.
Requirements
- Node.js 18 or newer (uses the built-in
fetch)
Installation
pnpm add featurable
# or
npm install featurable
# or
yarn add featurableAuthentication
Create an API key in your Featurable developer settings
and provide it to the client, either directly or via the FEATURABLE_API_KEY
environment variable.
Quick start
import { Featurable } from 'featurable';
const client = new Featurable({
apiKey: process.env.FEATURABLE_API_KEY,
});
const widget = await client.widgets.retrieve('your-widget-uuid');
console.log(
`${widget.gbpLocationSummary.rating}★ from ${widget.gbpLocationSummary.reviewsCount} reviews`,
);
for (const review of widget.reviews) {
console.log(`${review.author.name}: ${review.rating.value}/${review.rating.max}`);
console.log(review.text);
}CommonJS is supported too:
const { Featurable } = require('featurable');Configuration
const client = new Featurable({
apiKey: '...', // defaults to process.env.FEATURABLE_API_KEY
baseURL: 'https://featurable.com/api/v2', // override the API base URL
timeout: 60_000, // per-request timeout in ms (0 disables)
maxRetries: 2, // retries for transient failures
defaultHeaders: {}, // headers added to every request
fetch: globalThis.fetch, // custom fetch implementation
});Per-request options
Every resource method accepts optional overrides:
const controller = new AbortController();
const widget = await client.widgets.retrieve('your-widget-uuid', {
timeout: 10_000,
maxRetries: 0,
signal: controller.signal,
headers: { 'X-Trace-Id': 'abc123' },
});Error handling
All errors extend FeaturableError. HTTP errors are APIError instances with a
status code, and are further specialized so you can branch on the failure:
import {
Featurable,
APIError,
NotFoundError,
RateLimitError,
AuthenticationError,
} from 'featurable';
try {
await client.widgets.retrieve('missing');
} catch (error) {
if (error instanceof NotFoundError) {
// 404 — the widget does not exist
} else if (error instanceof RateLimitError) {
// 429 — retry later
} else if (error instanceof AuthenticationError) {
// 401 — check your API key
} else if (error instanceof APIError) {
console.error(error.status, error.requestId, error.body);
} else {
throw error;
}
}| Error | When |
| ----------------------- | --------------------------------- |
| BadRequestError | HTTP 400 |
| AuthenticationError | HTTP 401 |
| PermissionDeniedError | HTTP 403 |
| NotFoundError | HTTP 404 |
| ConflictError | HTTP 409 |
| RateLimitError | HTTP 429 |
| InternalServerError | HTTP 5xx |
| APITimeoutError | Request exceeded the timeout |
| APIConnectionError | Network failure / request aborted |
Retries
By default the client retries up to maxRetries (2) times on network errors and
408, 409, 429, and 5xx responses, using exponential backoff with jitter.
When the API returns a Retry-After header, it is honored.
API
client.widgets.retrieve(uuid, options?)
Retrieve a widget and its reviews by UUID. Returns a Widget.
Development
See CONTRIBUTING.md.
