propublica-nonprofit-explorer-sdk
Version:
SDK for ProPublica Nonprofit Explorer API
136 lines • 4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Client = exports.APIError = void 0;
const constants_1 = require("./constants");
const organization_zod_1 = require("./models/organization.zod");
const search_zod_1 = require("./models/search.zod");
class APIError extends Error {
constructor(message) {
super(message);
this.name = 'APIError';
}
}
exports.APIError = APIError;
class Client {
/**
* Search for organizations
*
* @param params Search parameters
* @returns
*/
async search(params) {
const validatedParams = (0, search_zod_1.validateSearchRequest)(params);
const response = await this.get('/search.json', validatedParams);
return (0, search_zod_1.validateSearchResponse)(response);
}
/**
* Get an organization by EIN
*
* @param ein Employer Identification Number
* @returns Organization object
*/
async organization(ein) {
this.validateEIN(ein);
try {
const response = await this.get(`/organizations/${ein}.json`);
return (0, organization_zod_1.validateOrganizationResponse)(response);
}
catch (err) {
this.handleError(err);
}
}
validateEIN(ein) {
if (!Number.isInteger(ein) || ein.toString().length !== 9) {
throw new Error('EIN must be a 9-digit integer');
}
}
/**
* Call a GET to a specific API path
*
* @param path API path to fetch
* @param params Parameters
* @returns
*/
async get(path, params = {}) {
const stringParams = Object.fromEntries(Object.entries(params).map(([key, value]) => [key, value.toString()]));
const response = await this.request('GET', path, stringParams);
return this.parseResponse(response);
}
/**
* Parse the API response
*
* @param response API response
* @returns
*/
async parseResponse(response) {
if (response.body == null) {
return null;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let result = '';
for await (const chunk of this.readChunks(reader)) {
result += decoder.decode(chunk);
}
return JSON.parse(result);
}
/**
* Read chunks from API response
*
* @param reader Stream reader
*/
async *readChunks(reader) {
while (true) {
const { done, value } = await reader.read();
if (done)
break;
yield value;
}
}
/**
* Make a request
*
* @param method HTTP method to be used
* @param path URL path to call
* @param params Parameters
* @returns
*/
async request(method, path, params) {
try {
// TODO: Set User-Agent header
let url = constants_1.API_BASE_URL + path;
if (Object.keys(params).length > 0) {
const query = '?' + new URLSearchParams(params).toString();
url += query;
}
const response = await fetch(url, {
headers: {
'User-Agent': 'NonProfitExplorerSDK/' + constants_1.SDK_VERSION,
},
method: method,
});
return response;
}
catch (err) {
if (err instanceof Error) {
throw new APIError(err.message);
}
else {
throw new APIError('An unknown error occurred');
}
}
}
handleError(err) {
if (err instanceof APIError) {
throw err;
}
else if (err instanceof Error) {
throw new APIError(err.message);
}
else {
throw new APIError('An unknown error occurred');
}
}
}
exports.Client = Client;
//# sourceMappingURL=client.js.map