A client library for working with the Zoey API.
- Minimal dependencies (zod as peer dependency)
- Built as both CommonJS and ESM
- Fully type-safe
- Tested on MacOS and Ubuntu 20.04
- Mock client for testing
- Node 18+ (uses native Fetch API)
- Zod 4.0.0+ (peer dependency)
Install the package with:
``sh`
npm install @eldev/zoey-client-node
Pass the OAuth 1.0a credentials and site URL (see Zoey REST docs for instructions) as a ZoeyClientConfig object to the ZoeyClient.
You can optionally set a timeout for the request, but be aware some requests (like converting cart to checkout) can take 10+ seconds.
`ts
import { ZoeyClient } from "zoey-client-node";
import type { ZoeyClientConfig } from "zoey-client-node/types";
const configOptions: ZoeyClientConfig = {
baseUrl: "https://zoey-site-url.com/api/rest",
// timeout: 15_000
apiKey: "zoey_api_key_2342344235"
}
const zoey = new ZoeyClient(configOptions); // Throws ZoeyError with type: 'configuration'
`
Resource methods return either data or throw a ZoeyError.
You can also access the embedded HttpClient that has 3 methods: request, requestWithSchema, requestWithPagination.RequestOptions
Each takes a object.requestWithSchema additionally takes a schema.requestWithPagination also takes a PaginationOptions to control the amount of results and a transformFn to parse the page results.
requestWithPagination returns an AsyncIterableIterator that can be consumed with a for await loop.
`ts
const Account = z.object({ id: z.string() });
type Account = z.infer
const requestOptions: RequestOptions = {
path: "/accounts/account"
queryParams: { id: "500" },
timeout: 5_000, // override default/initialized timeout
method: "GET", // defaults to GET
// body: some_body_object
};
// Raw request
await zoey.client.request(requestOptions); // => unknown
// Parsed request
await zoey.client.requestWithSchema(
requestOptions,
schema: Account,
); // => Account
// Pagination
const paginationOptions: PaginationOptions = {
maxResults: 50,
orderBy: 'created_at'
orderDir: 'DESC'
}
const transformFn = (data: unknown) => z.array(Account).parse(data); // Parses list page into array
const iter = zoey.client.requestWithPagination(
requestOptions,
transformFn,
paginationOptions
)
// Iterate through each record and lazily fetch next page
for await (const account of iter) {
doSomething(account)
};
// Resource methods
// Get single records are explicitly named as they can use different identifiers
await zoey.accounts.getByAccountNumber("account_number_here") // Account
const listOpts: ZoeyListOptions = { maxResults: 50, orderBy: 'created_at', orderDir: 'DESC' }
const iter = zoey.accounts.list(listOpts)
for await (const account of iter) {} // Lazily fetch each page as you loop through
const all = Array.fromAsync(iter) // Loop through all and collect into array
`
ZoeyError extends Error and always includes a message property and a type property.
Based on the type code there may be other properties like the URL path, full response body, etc.
| Error Code | Description |
| --------------------- | ----------------------------------------------------------------------------------------- |
| configuration | An invalid ZoeyClientConfig object passed to the client constructor. |connection
| | There was an issue connecting to the Zoey API server. This is an error thrown by fetch. |invalid_return_type
| | The return type from the Zoey API did not match the schema. |bad_json
| | The response body could not be parsed and threw a SyntaxError. |timeout
| | The fetch request threw a TimeoutError due to AbortSignal.timeout() |bad_request
| | The API returned a 400 status. |authentication
| | The API returned a 401 status. |permission
| | The API returned a 403 status. |not_found
| | The API returned a 404 status. |too_many_requests
| | The API returned a 429 status. |api_error
| | The API returned 500 or any other not specified status. |unknown
| | The fetch request threw something that was not an instance of Error`. |
- Add live e2e tests that record data for msw