sec-api
Version:
sec.gov EDGAR API Wrapper
209 lines (175 loc) • 4.26 kB
JavaScript
const io = require('socket.io-client');
const config = require('./config');
const events = require('events');
const axios = require('axios');
const store = { apiKey: '' };
const setApiKey = (apiKey) => {
store.apiKey = apiKey;
};
/*
* Stream API
*/
const streamApiStore = {};
const initSocket = (apiKey) => {
const uri = config.io.server + '/' + config.io.namespace.allFilings;
const params = {
query: { apiKey },
transports: ['websocket'], // ensure traffic goes through load balancer
};
streamApiStore.socket = io(uri, params);
streamApiStore.socket.on('connect', () =>
console.log('Socket connected to', uri)
);
streamApiStore.socket.on('filing', handleNewFiling);
streamApiStore.socket.on('filings', handleNewFilings);
streamApiStore.socket.on('error', console.error);
};
const handleNewFiling = (filing) => {
streamApiStore.eventEmitter.emit('filing', filing);
};
const handleNewFilings = (filings) => {
streamApiStore.eventEmitter.emit('filings', filings);
};
const close = () => {
if (streamApiStore.socket.close) {
streamApiStore.socket.close();
}
};
const connect = (apiKey) => {
setApiKey(apiKey);
initSocket(apiKey);
streamApiStore.eventEmitter = new events.EventEmitter();
modules.streamApi.on = streamApiStore.eventEmitter.on;
return streamApiStore.eventEmitter;
};
/*
* Query API
*/
/**
* Query filings
*
* @param {String} query The query string
* @returns {Object} The response from the API
*/
const getFilingsQuery = async (query) => {
const options = {
method: 'post',
url: config.queryApi.endpoint,
headers: { Authorization: store.apiKey },
data: query,
};
const { data } = await axios(options);
return data;
};
/**
* Full-text Search API
*/
const getFilingsFullText = async (query) => {
const options = {
method: 'post',
url: config.fullTextApi.endpoint,
headers: { Authorization: store.apiKey },
data: query,
};
const { data } = await axios(options);
return data;
};
/**
* Render API
*/
const getFilingContent = async (url, type = 'html') => {
let _url;
if (type === 'pdf') {
_url = config.renderApi.endpoint + +'&type=' + type + '&url=' + url;
} else {
const filename = url.replace(
'https://www.sec.gov/Archives/edgar/data/',
''
);
_url = config.downloadApi.endpoint + filename + '?token=' + store.apiKey;
}
const options = {
method: 'get',
url: _url,
};
const { data } = await axios(options);
return data;
};
/**
* XBRL-to-JSON converter and parser
*/
const xbrlToJson = async ({ htmUrl, xbrlUrl, accessionNo } = {}) => {
if (!htmUrl && !xbrlUrl && !accessionNo) {
throw new Error(
'Please provide one of the following arguments: htmUrl, xbrlUrl or accessionNo'
);
}
let requestUrl = config.xbrlToJsonApi.endpoint + '?token=' + store.apiKey;
if (htmUrl) {
requestUrl += '&htm-url=' + htmUrl;
}
if (xbrlUrl) {
requestUrl += '&xbrl-url=' + xbrlUrl;
}
if (accessionNo) {
requestUrl += '&accession-no=' + accessionNo;
}
const { data } = await axios.get(requestUrl);
return data;
};
/**
* Extractor API
*/
const getSection = async (filingUrl, section = '1A', returnType = 'text') => {
if (!filingUrl || !filingUrl.length) {
throw new Error('No valid filing URL provided');
}
const requestUrl =
config.extractorApi.endpoint +
`?token=${store.apiKey}&url=${filingUrl}&item=${section}&type=${returnType}`;
const { data } = await axios.get(requestUrl);
return data;
};
/**
* Helpers
*/
const modules = {
setApiKey,
streamApi: {
setApiKey,
connect,
close,
},
queryApi: {
setApiKey,
getFilings: getFilingsQuery,
},
fullTextSearchApi: {
setApiKey,
getFilings: getFilingsFullText,
},
renderApi: {
setApiKey,
getFilingContent,
},
xbrlApi: {
setApiKey,
xbrlToJson,
},
extractorApi: {
setApiKey,
getSection,
},
};
module.exports = modules;
/**
* Command Line Execution - Stream API
*/
if (require.main === module) {
const apiKey = process.argv[2];
const emitter = connect(apiKey);
emitter.on('filing', (filing) =>
console.log(JSON.stringify(filing, null, 1))
);
}