sec-edgar-api 0.0.2 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/build/downloader.d.ts +6 -0
- package/build/downloader.js +9 -0
- package/build/services/Client/Client.d.ts +44 -0
- package/build/services/Client/Client.js +104 -0
- package/build/services/Client/index.d.ts +3 -0
- package/build/services/Client/index.js +19 -0
- package/build/services/FactsDownloader/Downloader.d.ts +26 -0
- package/build/services/FactsDownloader/Downloader.js +102 -0
- package/build/services/FactsDownloader/FactsDownloader.d.ts +37 -0
- package/build/services/FactsDownloader/FactsDownloader.js +131 -0
- package/build/services/FactsDownloader/Unzipper.d.ts +40 -0
- package/build/services/FactsDownloader/Unzipper.js +40 -0
- package/build/services/FactsDownloader/index.d.ts +2 -0
- package/build/services/FactsDownloader/index.js +4 -0
- package/build/services/ReportParser/ReportParser.d.ts +4 -0
- package/build/services/ReportParser/ReportParser.js +19 -0
- package/build/services/SecEdgarApi/FactsDownloader.js +0 -1
- package/build/services/SecEdgarApi/SecConnector.d.ts +1 -1
- package/build/services/SecEdgarApi/SecConnector.js +1 -1
- package/build/services/SecEdgarApi/SecEdgarApi.d.ts +6 -12
- package/build/services/SecEdgarApi/SecEdgarApi.js +7 -19
- package/build/services/SecEdgarApi/Throttler.d.ts +1 -2
- package/build/services/SecEdgarApi/Throttler.js +12 -12
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Fetch and parse earnings reports and other documents filed with the SEC using the EDGAR API.
|
|
4
4
|
This package is focused on the earnings reports for stock analysis.
|
|
5
5
|
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```SH
|
|
9
|
+
npm install sec-edgar-api
|
|
10
|
+
```
|
|
11
|
+
|
|
6
12
|
## Report Interface
|
|
7
13
|
|
|
8
14
|
Reports are all returned as a uniform interface:
|
|
@@ -100,10 +106,12 @@ const reports = await secEdgarApi.getReports({ symbol: 'AAPL' })
|
|
|
100
106
|
or download all data from the SEC website and read directly from the files so you don't have to worry about rate limiting.
|
|
101
107
|
|
|
102
108
|
```TS
|
|
109
|
+
import { factsDownloader } from 'sec-edgar-api/downloader'
|
|
110
|
+
|
|
103
111
|
const downloadDirectory = './downloads/companyfacts'
|
|
104
112
|
|
|
105
113
|
// Download companyfacts directory from sec.gov (over 15GB)
|
|
106
|
-
await
|
|
114
|
+
await factsDownloader.downloadCompanyFactsDirectory({
|
|
107
115
|
outputDirname: downloadDirectory,
|
|
108
116
|
onDownloadComplete: () => process.stdout.write('\n'),
|
|
109
117
|
onChunk: ({ percentComplete, stage }) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.factsDownloader = void 0;
|
|
4
|
+
var FactsDownloader_1 = require("./services/FactsDownloader");
|
|
5
|
+
/**
|
|
6
|
+
* Downloads companyfacts.zip from sec.gov and extracts the directory
|
|
7
|
+
*/
|
|
8
|
+
var factsDownloader = new FactsDownloader_1.default();
|
|
9
|
+
exports.factsDownloader = factsDownloader;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { ClientRequest, IncomingMessage, RequestOptions } from 'http';
|
|
4
|
+
type Primitive = string | number | boolean | null | undefined;
|
|
5
|
+
interface HttpClient {
|
|
6
|
+
request: (options: string | URL | RequestOptions, callback?: (res: IncomingMessage) => void) => ClientRequest;
|
|
7
|
+
}
|
|
8
|
+
export interface OnChunkData {
|
|
9
|
+
percentComplete: number;
|
|
10
|
+
chunk: Buffer;
|
|
11
|
+
}
|
|
12
|
+
export interface ClientResponse {
|
|
13
|
+
statusCode: number;
|
|
14
|
+
message: string;
|
|
15
|
+
data: Buffer | null;
|
|
16
|
+
}
|
|
17
|
+
export interface RequestParams {
|
|
18
|
+
url: string;
|
|
19
|
+
headers?: Record<string, string>;
|
|
20
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
21
|
+
data?: string | Record<string, Primitive | object>;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
onError?: (err: Error) => void;
|
|
24
|
+
onChunk?: (data: OnChunkData) => void;
|
|
25
|
+
onResponse?: (response: IncomingMessage) => void;
|
|
26
|
+
onSuccess?: (response: ClientResponse) => void;
|
|
27
|
+
resolveData?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface ClientArgs {
|
|
30
|
+
httpClient?: HttpClient;
|
|
31
|
+
defaultHeaders?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
export interface IClient {
|
|
34
|
+
request(params: RequestParams): Promise<ClientResponse>;
|
|
35
|
+
setDefaultHeaders?(headers: Record<string, string>): void;
|
|
36
|
+
}
|
|
37
|
+
export default class Client implements IClient {
|
|
38
|
+
private readonly httpClient;
|
|
39
|
+
private defaultHeaders;
|
|
40
|
+
constructor(args?: ClientArgs);
|
|
41
|
+
setDefaultHeaders(headers: Record<string, string>): void;
|
|
42
|
+
request(params: RequestParams): Promise<ClientResponse>;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
var https = require("https");
|
|
15
|
+
var Client = /** @class */ (function () {
|
|
16
|
+
function Client(args) {
|
|
17
|
+
if (args === void 0) { args = {
|
|
18
|
+
httpClient: https,
|
|
19
|
+
defaultHeaders: {
|
|
20
|
+
// this can be any user agent, just not empty
|
|
21
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 RuxitSynthetic/1.0 v1060014908909962014 t8797611264074608560 ath259cea6f altpriv cvcv=2 smf=0',
|
|
22
|
+
},
|
|
23
|
+
}; }
|
|
24
|
+
var httpClient = args.httpClient, defaultHeaders = args.defaultHeaders;
|
|
25
|
+
this.httpClient = httpClient !== null && httpClient !== void 0 ? httpClient : https;
|
|
26
|
+
this.defaultHeaders = defaultHeaders !== null && defaultHeaders !== void 0 ? defaultHeaders : {};
|
|
27
|
+
}
|
|
28
|
+
Client.prototype.setDefaultHeaders = function (headers) {
|
|
29
|
+
this.defaultHeaders = headers;
|
|
30
|
+
};
|
|
31
|
+
Client.prototype.request = function (params) {
|
|
32
|
+
var _this = this;
|
|
33
|
+
var url = params.url, data = params.data, headers = params.headers, onChunk = params.onChunk, onResponse = params.onResponse, onError = params.onError, onSuccess = params.onSuccess, _a = params.resolveData, resolveData = _a === void 0 ? true : _a, _b = params.method, method = _b === void 0 ? 'GET' : _b, _c = params.timeout, timeout = _c === void 0 ? 86400000 : _c;
|
|
34
|
+
var allHeaders = __assign(__assign({}, this.defaultHeaders), headers);
|
|
35
|
+
return new Promise(function (resolve, reject) {
|
|
36
|
+
var responseData = '';
|
|
37
|
+
var request = _this.httpClient.request(url, function (res) {
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
var lengthTotal = parseInt((_a = res.headers['content-length']) !== null && _a !== void 0 ? _a : '0');
|
|
40
|
+
var lengthCurrent = 0;
|
|
41
|
+
onResponse === null || onResponse === void 0 ? void 0 : onResponse(res);
|
|
42
|
+
if (res.statusCode !== 200) {
|
|
43
|
+
reject({
|
|
44
|
+
statusCode: (_b = res.statusCode) !== null && _b !== void 0 ? _b : 400,
|
|
45
|
+
message: (_c = res.statusMessage) !== null && _c !== void 0 ? _c : 'Bad Request',
|
|
46
|
+
data: null,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
res.on('data', function (chunk) {
|
|
50
|
+
lengthCurrent += chunk.length;
|
|
51
|
+
if (resolveData) {
|
|
52
|
+
responseData += chunk;
|
|
53
|
+
}
|
|
54
|
+
onChunk === null || onChunk === void 0 ? void 0 : onChunk({
|
|
55
|
+
percentComplete: lengthCurrent / lengthTotal,
|
|
56
|
+
chunk: Buffer.from(chunk),
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
res.on('error', function (err) {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
onError === null || onError === void 0 ? void 0 : onError(err);
|
|
62
|
+
reject({
|
|
63
|
+
statusCode: (_a = res.statusCode) !== null && _a !== void 0 ? _a : 400,
|
|
64
|
+
message: (_b = res.statusMessage) !== null && _b !== void 0 ? _b : 'Bad Request',
|
|
65
|
+
data: null,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
res.on('end', function () {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
var buffer = Buffer.from(responseData);
|
|
71
|
+
var clientResponse = {
|
|
72
|
+
statusCode: (_a = res.statusCode) !== null && _a !== void 0 ? _a : 200,
|
|
73
|
+
message: (_b = res.statusMessage) !== null && _b !== void 0 ? _b : 'OK',
|
|
74
|
+
data: buffer,
|
|
75
|
+
};
|
|
76
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(clientResponse);
|
|
77
|
+
resolve(clientResponse);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
request.on('timeout', function () {
|
|
81
|
+
request.destroy();
|
|
82
|
+
reject({
|
|
83
|
+
statusCode: null,
|
|
84
|
+
message: 'Connection Timeout',
|
|
85
|
+
data: null,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
request.setTimeout(timeout, function () { return reject("timeout after ".concat(timeout, "ms")); });
|
|
89
|
+
for (var key in allHeaders) {
|
|
90
|
+
request.setHeader(key, allHeaders[key]);
|
|
91
|
+
}
|
|
92
|
+
if (data) {
|
|
93
|
+
if (typeof data === 'string')
|
|
94
|
+
request.write(data);
|
|
95
|
+
else
|
|
96
|
+
request.write(JSON.stringify(data));
|
|
97
|
+
}
|
|
98
|
+
request.method = method;
|
|
99
|
+
request.end();
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
return Client;
|
|
103
|
+
}());
|
|
104
|
+
exports.default = Client;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
var Client_1 = require("./Client");
|
|
18
|
+
exports.default = Client_1.default;
|
|
19
|
+
__exportStar(require("./Client"), exports);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { WriteStream } from 'fs';
|
|
3
|
+
import { IClient, RequestParams } from '../Client';
|
|
4
|
+
export interface DownloadParams extends RequestParams {
|
|
5
|
+
filename: string;
|
|
6
|
+
createDirIfNotExists?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface IDownloader {
|
|
9
|
+
download(params: DownloadParams): Promise<boolean>;
|
|
10
|
+
}
|
|
11
|
+
interface FileManager {
|
|
12
|
+
createWriteStream(path: string): WriteStream;
|
|
13
|
+
existsSync(path: string): boolean;
|
|
14
|
+
mkdirSync(path: string): void;
|
|
15
|
+
}
|
|
16
|
+
interface DownloaderArgs {
|
|
17
|
+
client: IClient;
|
|
18
|
+
fileManager: FileManager;
|
|
19
|
+
}
|
|
20
|
+
export default class Downlaoder implements IDownloader {
|
|
21
|
+
private readonly client;
|
|
22
|
+
private readonly fileManager;
|
|
23
|
+
constructor(args?: DownloaderArgs);
|
|
24
|
+
download(params: DownloadParams): Promise<boolean>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
50
|
+
var t = {};
|
|
51
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
52
|
+
t[p] = s[p];
|
|
53
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
54
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
55
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
56
|
+
t[p[i]] = s[p[i]];
|
|
57
|
+
}
|
|
58
|
+
return t;
|
|
59
|
+
};
|
|
60
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
|
+
var fs = require("fs");
|
|
62
|
+
var Client_1 = require("../Client");
|
|
63
|
+
var Downlaoder = /** @class */ (function () {
|
|
64
|
+
function Downlaoder(args) {
|
|
65
|
+
if (args === void 0) { args = { client: new Client_1.default(), fileManager: fs }; }
|
|
66
|
+
var client = args.client, fileManager = args.fileManager;
|
|
67
|
+
this.client = client;
|
|
68
|
+
this.fileManager = fileManager;
|
|
69
|
+
}
|
|
70
|
+
Downlaoder.prototype.download = function (params) {
|
|
71
|
+
var _this = this;
|
|
72
|
+
var filename = params.filename, onSuccess = params.onSuccess, onError = params.onError, _a = params.createDirIfNotExists, createDirIfNotExists = _a === void 0 ? false : _a, rest = __rest(params, ["filename", "onSuccess", "onError", "createDirIfNotExists"]);
|
|
73
|
+
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
74
|
+
var dir, file;
|
|
75
|
+
return __generator(this, function (_a) {
|
|
76
|
+
dir = filename.substring(0, filename.lastIndexOf('/'));
|
|
77
|
+
if (dir.length > 0 && createDirIfNotExists && !this.fileManager.existsSync(dir)) {
|
|
78
|
+
this.fileManager.mkdirSync(dir);
|
|
79
|
+
}
|
|
80
|
+
file = this.fileManager.createWriteStream(filename);
|
|
81
|
+
file.on('close', function () { return resolve(true); });
|
|
82
|
+
file.on('finish', function () { return file.close(); });
|
|
83
|
+
file.on('error', function (err) {
|
|
84
|
+
file.destroy();
|
|
85
|
+
onError === null || onError === void 0 ? void 0 : onError(err);
|
|
86
|
+
reject(false);
|
|
87
|
+
});
|
|
88
|
+
this.client
|
|
89
|
+
.request(__assign(__assign({ onError: onError }, rest), { onResponse: function (res) {
|
|
90
|
+
var _a;
|
|
91
|
+
res.pipe(file);
|
|
92
|
+
(_a = rest.onResponse) === null || _a === void 0 ? void 0 : _a.call(rest, res);
|
|
93
|
+
} }))
|
|
94
|
+
.then(function (res) { return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(res); })
|
|
95
|
+
.catch(function () { return reject(false); });
|
|
96
|
+
return [2 /*return*/];
|
|
97
|
+
});
|
|
98
|
+
}); });
|
|
99
|
+
};
|
|
100
|
+
return Downlaoder;
|
|
101
|
+
}());
|
|
102
|
+
exports.default = Downlaoder;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IDownloader } from './Downloader';
|
|
3
|
+
import Unzipper from './Unzipper';
|
|
4
|
+
interface FactsDownloaderArgs {
|
|
5
|
+
downloader: IDownloader;
|
|
6
|
+
unzipper: Unzipper;
|
|
7
|
+
}
|
|
8
|
+
interface OnChunkData {
|
|
9
|
+
percentComplete: number;
|
|
10
|
+
chunk: Buffer;
|
|
11
|
+
stage: 'download' | 'unzip';
|
|
12
|
+
}
|
|
13
|
+
export interface DownloadCompanyFactsDirectoryParams {
|
|
14
|
+
outputDirname: string;
|
|
15
|
+
unzip?: boolean;
|
|
16
|
+
onChunk?: (data: OnChunkData) => void;
|
|
17
|
+
onDownloadComplete?: () => void;
|
|
18
|
+
onComplete?: () => void;
|
|
19
|
+
onError?: (err: Error) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface IFactsDownloader {
|
|
22
|
+
downloadCompanyFactsDirectory(params: DownloadCompanyFactsDirectoryParams): Promise<boolean>;
|
|
23
|
+
}
|
|
24
|
+
export default class FactsDownloader implements IFactsDownloader {
|
|
25
|
+
private readonly unzipper;
|
|
26
|
+
private readonly downloader;
|
|
27
|
+
constructor(args?: FactsDownloaderArgs);
|
|
28
|
+
/**
|
|
29
|
+
* Downloads the companyfacts.zip file and extracts the directory containing all company
|
|
30
|
+
* reports available from sec.gov. After downloading, you can use factFileReader and reportParser
|
|
31
|
+
* to get and read reports.
|
|
32
|
+
*
|
|
33
|
+
* Note: Over 15GB of data is downloaded and extracted.
|
|
34
|
+
*/
|
|
35
|
+
downloadCompanyFactsDirectory(params: DownloadCompanyFactsDirectoryParams): Promise<boolean>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
var Downloader_1 = require("./Downloader");
|
|
51
|
+
var Unzipper_1 = require("./Unzipper");
|
|
52
|
+
var FactsDownloader = /** @class */ (function () {
|
|
53
|
+
function FactsDownloader(args) {
|
|
54
|
+
if (args === void 0) { args = {
|
|
55
|
+
downloader: new Downloader_1.default(),
|
|
56
|
+
unzipper: new Unzipper_1.default(),
|
|
57
|
+
}; }
|
|
58
|
+
var unzipper = args.unzipper, downloader = args.downloader;
|
|
59
|
+
this.unzipper = unzipper;
|
|
60
|
+
this.downloader = downloader;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Downloads the companyfacts.zip file and extracts the directory containing all company
|
|
64
|
+
* reports available from sec.gov. After downloading, you can use factFileReader and reportParser
|
|
65
|
+
* to get and read reports.
|
|
66
|
+
*
|
|
67
|
+
* Note: Over 15GB of data is downloaded and extracted.
|
|
68
|
+
*/
|
|
69
|
+
FactsDownloader.prototype.downloadCompanyFactsDirectory = function (params) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
71
|
+
var outputDirname, onChunk, onDownloadComplete, onError, onComplete, _a, unzip;
|
|
72
|
+
var _this = this;
|
|
73
|
+
return __generator(this, function (_b) {
|
|
74
|
+
outputDirname = params.outputDirname, onChunk = params.onChunk, onDownloadComplete = params.onDownloadComplete, onError = params.onError, onComplete = params.onComplete, _a = params.unzip, unzip = _a === void 0 ? true : _a;
|
|
75
|
+
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
76
|
+
var filename, e_1;
|
|
77
|
+
return __generator(this, function (_a) {
|
|
78
|
+
switch (_a.label) {
|
|
79
|
+
case 0:
|
|
80
|
+
filename = "".concat(outputDirname, ".zip");
|
|
81
|
+
_a.label = 1;
|
|
82
|
+
case 1:
|
|
83
|
+
_a.trys.push([1, 5, , 6]);
|
|
84
|
+
// download from sec
|
|
85
|
+
return [4 /*yield*/, this.downloader.download({
|
|
86
|
+
url: 'https://www.sec.gov/Archives/edgar/daily-index/xbrl/companyfacts.zip',
|
|
87
|
+
filename: filename,
|
|
88
|
+
createDirIfNotExists: true,
|
|
89
|
+
resolveData: false,
|
|
90
|
+
headers: {
|
|
91
|
+
'Accept-Encoding': 'gzip, deflate',
|
|
92
|
+
},
|
|
93
|
+
onError: function (err) { return reject(err); },
|
|
94
|
+
onChunk: onChunk ? function (data) { return onChunk === null || onChunk === void 0 ? void 0 : onChunk(__assign(__assign({}, data), { stage: 'download' })); } : undefined,
|
|
95
|
+
})];
|
|
96
|
+
case 2:
|
|
97
|
+
// download from sec
|
|
98
|
+
_a.sent();
|
|
99
|
+
onDownloadComplete === null || onDownloadComplete === void 0 ? void 0 : onDownloadComplete();
|
|
100
|
+
if (!unzip) return [3 /*break*/, 4];
|
|
101
|
+
// unzip companyfacts.zip
|
|
102
|
+
return [4 /*yield*/, this.unzipper.unzip({
|
|
103
|
+
inputFilename: filename,
|
|
104
|
+
outputDirname: outputDirname,
|
|
105
|
+
deleteOriginal: true,
|
|
106
|
+
onError: function (err) { return reject(err); },
|
|
107
|
+
onChunk: onChunk ? function (data) { return onChunk === null || onChunk === void 0 ? void 0 : onChunk(__assign(__assign({}, data), { stage: 'unzip' })); } : undefined,
|
|
108
|
+
})];
|
|
109
|
+
case 3:
|
|
110
|
+
// unzip companyfacts.zip
|
|
111
|
+
_a.sent();
|
|
112
|
+
_a.label = 4;
|
|
113
|
+
case 4:
|
|
114
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
115
|
+
resolve(true);
|
|
116
|
+
return [3 /*break*/, 6];
|
|
117
|
+
case 5:
|
|
118
|
+
e_1 = _a.sent();
|
|
119
|
+
onError === null || onError === void 0 ? void 0 : onError(e_1);
|
|
120
|
+
reject(e_1);
|
|
121
|
+
return [3 /*break*/, 6];
|
|
122
|
+
case 6: return [2 /*return*/];
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}); })];
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
return FactsDownloader;
|
|
130
|
+
}());
|
|
131
|
+
exports.default = FactsDownloader;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import { ReadStream } from 'fs';
|
|
5
|
+
import { ParseStream } from 'unzipper';
|
|
6
|
+
interface IFileManager {
|
|
7
|
+
createReadStream(path: string): ReadStream;
|
|
8
|
+
unlinkSync(path: string): void;
|
|
9
|
+
statSync(path: string): fs.Stats;
|
|
10
|
+
}
|
|
11
|
+
interface IFileUnzipper {
|
|
12
|
+
Extract(options: {
|
|
13
|
+
path: string;
|
|
14
|
+
}): ParseStream;
|
|
15
|
+
}
|
|
16
|
+
interface UnzipperArgs {
|
|
17
|
+
unzipper: IFileUnzipper;
|
|
18
|
+
fileManager: IFileManager;
|
|
19
|
+
}
|
|
20
|
+
interface OnChunkData {
|
|
21
|
+
percentComplete: number;
|
|
22
|
+
chunk: Buffer;
|
|
23
|
+
}
|
|
24
|
+
interface UnzipParams {
|
|
25
|
+
inputFilename: string;
|
|
26
|
+
outputDirname: string;
|
|
27
|
+
onChunk?: (data: OnChunkData) => void;
|
|
28
|
+
onError?: (err: Error) => void;
|
|
29
|
+
deleteOriginal?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface IUnzipper {
|
|
32
|
+
unzip(params: UnzipParams): Promise<any>;
|
|
33
|
+
}
|
|
34
|
+
export default class Unzipper implements IUnzipper {
|
|
35
|
+
private readonly fileManager;
|
|
36
|
+
private readonly unzipper;
|
|
37
|
+
constructor(args?: UnzipperArgs);
|
|
38
|
+
unzip(params: UnzipParams): Promise<unknown>;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var fs = require("fs");
|
|
4
|
+
var _unzipper = require("unzipper");
|
|
5
|
+
var Unzipper = /** @class */ (function () {
|
|
6
|
+
function Unzipper(args) {
|
|
7
|
+
if (args === void 0) { args = { fileManager: fs, unzipper: _unzipper }; }
|
|
8
|
+
var fileManager = args.fileManager, unzipper = args.unzipper;
|
|
9
|
+
this.fileManager = fileManager;
|
|
10
|
+
this.unzipper = unzipper;
|
|
11
|
+
}
|
|
12
|
+
Unzipper.prototype.unzip = function (params) {
|
|
13
|
+
var _this = this;
|
|
14
|
+
var inputFilename = params.inputFilename, outputDirname = params.outputDirname, onChunk = params.onChunk, onError = params.onError, _a = params.deleteOriginal, deleteOriginal = _a === void 0 ? false : _a;
|
|
15
|
+
return new Promise(function (resolve, reject) {
|
|
16
|
+
var file = _this.fileManager.createReadStream(inputFilename);
|
|
17
|
+
var filesize = _this.fileManager.statSync(inputFilename).size;
|
|
18
|
+
var unzipped = _this.unzipper.Extract({ path: outputDirname });
|
|
19
|
+
var lengthCurrent = 0;
|
|
20
|
+
file.on('data', function (chunk) {
|
|
21
|
+
lengthCurrent += chunk.length;
|
|
22
|
+
var percentComplete = lengthCurrent / filesize;
|
|
23
|
+
onChunk === null || onChunk === void 0 ? void 0 : onChunk({ percentComplete: percentComplete, chunk: chunk });
|
|
24
|
+
});
|
|
25
|
+
file.pipe(unzipped);
|
|
26
|
+
file.on('end', function () {
|
|
27
|
+
if (deleteOriginal) {
|
|
28
|
+
_this.fileManager.unlinkSync(inputFilename);
|
|
29
|
+
}
|
|
30
|
+
resolve(true);
|
|
31
|
+
});
|
|
32
|
+
file.on('error', function (err) {
|
|
33
|
+
onError === null || onError === void 0 ? void 0 : onError(err);
|
|
34
|
+
reject(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
return Unzipper;
|
|
39
|
+
}());
|
|
40
|
+
exports.default = Unzipper;
|
|
@@ -35,6 +35,10 @@ export default class ReportParser {
|
|
|
35
35
|
* @see https://www.sec.gov/edgar/sec-api-documentation
|
|
36
36
|
*/
|
|
37
37
|
parseReportsRaw(companyFactListData: Pick<CompanyFactListData, 'facts'>, options?: ParseReportsOptions): ReportRaw[];
|
|
38
|
+
/**
|
|
39
|
+
* parseReportsRaw but removes meta data from the report
|
|
40
|
+
*/
|
|
41
|
+
parseReportsRawNoMeta(companyFactListData: Pick<CompanyFactListData, 'facts'>, options?: ParseReportsOptions): Record<string, number>[];
|
|
38
42
|
/**
|
|
39
43
|
* Avoids deep nesting logic while iteratating through company facts
|
|
40
44
|
*
|
|
@@ -53,6 +53,25 @@ var ReportParser = /** @class */ (function () {
|
|
|
53
53
|
ReportParser.prototype.parseReportsRaw = function (companyFactListData, options) {
|
|
54
54
|
return this.reportRawParser.parseReports(companyFactListData, options);
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* parseReportsRaw but removes meta data from the report
|
|
58
|
+
*/
|
|
59
|
+
ReportParser.prototype.parseReportsRawNoMeta = function (companyFactListData, options) {
|
|
60
|
+
var reportsRaw = this.parseReportsRaw(companyFactListData, options);
|
|
61
|
+
reportsRaw.forEach(function (reportRaw) {
|
|
62
|
+
var report = reportRaw;
|
|
63
|
+
delete report.dateFiled;
|
|
64
|
+
delete report.dateReport;
|
|
65
|
+
delete report.fiscalPeriod;
|
|
66
|
+
delete report.fiscalYear;
|
|
67
|
+
delete report.form;
|
|
68
|
+
delete report.frame;
|
|
69
|
+
delete report.isTTM;
|
|
70
|
+
delete report.reportType;
|
|
71
|
+
delete report.taxonomy;
|
|
72
|
+
});
|
|
73
|
+
return reportsRaw;
|
|
74
|
+
};
|
|
56
75
|
/**
|
|
57
76
|
* Avoids deep nesting logic while iteratating through company facts
|
|
58
77
|
*
|
|
@@ -65,7 +65,6 @@ var FactsDownloader = /** @class */ (function () {
|
|
|
65
65
|
var _this = this;
|
|
66
66
|
return __generator(this, function (_b) {
|
|
67
67
|
outputDirname = params.outputDirname, onChunk = params.onChunk, onDownloadComplete = params.onDownloadComplete, onError = params.onError, onComplete = params.onComplete, _a = params.unzip, unzip = _a === void 0 ? true : _a;
|
|
68
|
-
// writes download and unzip progress with percentage in terminal if useWriteProgressBar is true
|
|
69
68
|
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
70
69
|
var filename, e_1;
|
|
71
70
|
return __generator(this, function (_a) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CompanyFactFrame, CompanyFactListData, MultiCompanyFactFrame } from '../../types';
|
|
2
2
|
import { SubmissionList } from '../../types/submission.type';
|
|
3
|
-
import { IClient } from '
|
|
3
|
+
import { IClient } from '../Client';
|
|
4
4
|
import { IThrottler } from './Throttler';
|
|
5
5
|
interface SecApiArgs {
|
|
6
6
|
throttler: IThrottler;
|
|
@@ -37,7 +37,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
var cik_by_symbol_1 = require("../../util/cik-by-symbol");
|
|
40
|
-
var Client_1 = require("
|
|
40
|
+
var Client_1 = require("../Client");
|
|
41
41
|
var Throttler_1 = require("./Throttler");
|
|
42
42
|
/**
|
|
43
43
|
* Gets reports from companies filed with the SEC
|
|
@@ -2,12 +2,10 @@ import { CompanyFactFrame, CompanyFactListData, MultiCompanyFactFrame, ReportRaw
|
|
|
2
2
|
import ReportParser from '../ReportParser';
|
|
3
3
|
import { ParseReportsOptions } from '../ReportParser/ReportRawParser';
|
|
4
4
|
import ReportWrapper from '../ReportParser/ReportWrapper';
|
|
5
|
-
import { DownloadCompanyFactsDirectoryParams, IFactsDownloader } from './FactsDownloader';
|
|
6
5
|
import { GetFactFrameParams, GetFactParams, GetSymbolParams, ISecConnector } from './SecConnector';
|
|
7
6
|
interface SecEdgarApiArgs {
|
|
8
7
|
secConnector: ISecConnector;
|
|
9
8
|
reportParser: ReportParser;
|
|
10
|
-
factsDownloader: IFactsDownloader;
|
|
11
9
|
}
|
|
12
10
|
/**
|
|
13
11
|
* Gets company reports and filings from the SEC EDGAR API
|
|
@@ -19,7 +17,6 @@ interface SecEdgarApiArgs {
|
|
|
19
17
|
export default class SecEdgarApi {
|
|
20
18
|
private readonly reportParser;
|
|
21
19
|
private readonly secConnector;
|
|
22
|
-
private readonly factsDownloader;
|
|
23
20
|
constructor(args?: SecEdgarApiArgs);
|
|
24
21
|
/**
|
|
25
22
|
* endpoint: /submissions/CIK${cik}.json
|
|
@@ -70,11 +67,14 @@ export default class SecEdgarApi {
|
|
|
70
67
|
*/
|
|
71
68
|
getFactFrame(params: GetFactFrameParams): Promise<MultiCompanyFactFrame>;
|
|
72
69
|
/**
|
|
70
|
+
* Note: Properties that are not provied from report are calculated an may not be accurate,
|
|
71
|
+
* verify results finance.yahoo.com (ex: https://finance.yahoo.com/quote/AAPL/financials)
|
|
72
|
+
*
|
|
73
|
+
* Please contribute to improve resolving report properties: https://github.com/andyevers/sec-edgar-api
|
|
74
|
+
*
|
|
73
75
|
* Parses reports from company facts. Calculates missing properties and uses a single interface
|
|
74
76
|
* for all reports. This includes only 10-K and 10-Q annual and quarterly reports. To include
|
|
75
|
-
* all reports, use getReportsRaw
|
|
76
|
-
*
|
|
77
|
-
* Note that calculated properties are estimated if they are not available in the company facts.
|
|
77
|
+
* all reports, use getReportsRaw.
|
|
78
78
|
*/
|
|
79
79
|
getReports(params: GetSymbolParams): Promise<ReportWrapper[]>;
|
|
80
80
|
/**
|
|
@@ -82,11 +82,5 @@ export default class SecEdgarApi {
|
|
|
82
82
|
* for all reports.
|
|
83
83
|
*/
|
|
84
84
|
getReportsRaw(params: GetSymbolParams & ParseReportsOptions): Promise<ReportRaw[]>;
|
|
85
|
-
/**
|
|
86
|
-
* Downloads the companyfacts.zip file and extracts the directory containing all company
|
|
87
|
-
* reports available from sec.gov. After downloading, you can use factFileReader and reportParser
|
|
88
|
-
* to get and read reports.
|
|
89
|
-
*/
|
|
90
|
-
downloadCompanyFactsDirectory(params: DownloadCompanyFactsDirectoryParams): Promise<boolean>;
|
|
91
85
|
}
|
|
92
86
|
export {};
|
|
@@ -37,7 +37,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
var ReportParser_1 = require("../ReportParser");
|
|
40
|
-
var FactsDownloader_1 = require("./FactsDownloader");
|
|
41
40
|
var SecConnector_1 = require("./SecConnector");
|
|
42
41
|
/**
|
|
43
42
|
* Gets company reports and filings from the SEC EDGAR API
|
|
@@ -51,12 +50,10 @@ var SecEdgarApi = /** @class */ (function () {
|
|
|
51
50
|
if (args === void 0) { args = {
|
|
52
51
|
secConnector: new SecConnector_1.default(),
|
|
53
52
|
reportParser: new ReportParser_1.default(),
|
|
54
|
-
factsDownloader: new FactsDownloader_1.default(),
|
|
55
53
|
}; }
|
|
56
|
-
var secConnector = args.secConnector, reportParser = args.reportParser
|
|
54
|
+
var secConnector = args.secConnector, reportParser = args.reportParser;
|
|
57
55
|
this.secConnector = secConnector;
|
|
58
56
|
this.reportParser = reportParser;
|
|
59
|
-
this.factsDownloader = factsDownloader;
|
|
60
57
|
}
|
|
61
58
|
/**
|
|
62
59
|
* endpoint: /submissions/CIK${cik}.json
|
|
@@ -131,11 +128,14 @@ var SecEdgarApi = /** @class */ (function () {
|
|
|
131
128
|
});
|
|
132
129
|
};
|
|
133
130
|
/**
|
|
131
|
+
* Note: Properties that are not provied from report are calculated an may not be accurate,
|
|
132
|
+
* verify results finance.yahoo.com (ex: https://finance.yahoo.com/quote/AAPL/financials)
|
|
133
|
+
*
|
|
134
|
+
* Please contribute to improve resolving report properties: https://github.com/andyevers/sec-edgar-api
|
|
135
|
+
*
|
|
134
136
|
* Parses reports from company facts. Calculates missing properties and uses a single interface
|
|
135
137
|
* for all reports. This includes only 10-K and 10-Q annual and quarterly reports. To include
|
|
136
|
-
* all reports, use getReportsRaw
|
|
137
|
-
*
|
|
138
|
-
* Note that calculated properties are estimated if they are not available in the company facts.
|
|
138
|
+
* all reports, use getReportsRaw.
|
|
139
139
|
*/
|
|
140
140
|
SecEdgarApi.prototype.getReports = function (params) {
|
|
141
141
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -167,18 +167,6 @@ var SecEdgarApi = /** @class */ (function () {
|
|
|
167
167
|
});
|
|
168
168
|
});
|
|
169
169
|
};
|
|
170
|
-
/**
|
|
171
|
-
* Downloads the companyfacts.zip file and extracts the directory containing all company
|
|
172
|
-
* reports available from sec.gov. After downloading, you can use factFileReader and reportParser
|
|
173
|
-
* to get and read reports.
|
|
174
|
-
*/
|
|
175
|
-
SecEdgarApi.prototype.downloadCompanyFactsDirectory = function (params) {
|
|
176
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
177
|
-
return __generator(this, function (_a) {
|
|
178
|
-
return [2 /*return*/, this.factsDownloader.downloadCompanyFactsDirectory(params)];
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
};
|
|
182
170
|
return SecEdgarApi;
|
|
183
171
|
}());
|
|
184
172
|
exports.default = SecEdgarApi;
|
|
@@ -15,10 +15,10 @@ export interface IThrottler {
|
|
|
15
15
|
add: (fn: () => Promise<any>) => void;
|
|
16
16
|
}
|
|
17
17
|
export default class Throttler implements IThrottler {
|
|
18
|
+
private readonly decrementTimeouts;
|
|
18
19
|
private readonly queue;
|
|
19
20
|
private readonly results;
|
|
20
21
|
private readonly errors;
|
|
21
|
-
private countRunning;
|
|
22
22
|
private maxConcurrent;
|
|
23
23
|
private delayMs;
|
|
24
24
|
onProgress?: (data: OnProgressData) => void;
|
|
@@ -26,7 +26,6 @@ export default class Throttler implements IThrottler {
|
|
|
26
26
|
onError?: (err: any) => void;
|
|
27
27
|
onEnd?: (results: any[], errors: any[]) => void;
|
|
28
28
|
constructor(args?: ThrottlerArgs);
|
|
29
|
-
setMaxConcurrent(maxConcurrent: number): void;
|
|
30
29
|
setDelayMs(delayMs: number): void;
|
|
31
30
|
add(fn: () => Promise<any>): void;
|
|
32
31
|
private run;
|
|
@@ -39,10 +39,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
var Throttler = /** @class */ (function () {
|
|
40
40
|
function Throttler(args) {
|
|
41
41
|
if (args === void 0) { args = {}; }
|
|
42
|
-
var _a = args.maxConcurrent, maxConcurrent = _a === void 0 ?
|
|
42
|
+
var _a = args.maxConcurrent, maxConcurrent = _a === void 0 ? 10 : _a, _b = args.delayMs, delayMs = _b === void 0 ? 1100 : _b, onProgress = args.onProgress, onResult = args.onResult, onError = args.onError, onEnd = args.onEnd;
|
|
43
43
|
this.maxConcurrent = maxConcurrent;
|
|
44
44
|
this.delayMs = delayMs;
|
|
45
|
-
this.
|
|
45
|
+
this.decrementTimeouts = new Set();
|
|
46
46
|
this.queue = [];
|
|
47
47
|
this.results = [];
|
|
48
48
|
this.errors = [];
|
|
@@ -51,9 +51,6 @@ var Throttler = /** @class */ (function () {
|
|
|
51
51
|
this.onError = onError;
|
|
52
52
|
this.onEnd = onEnd;
|
|
53
53
|
}
|
|
54
|
-
Throttler.prototype.setMaxConcurrent = function (maxConcurrent) {
|
|
55
|
-
this.maxConcurrent = maxConcurrent;
|
|
56
|
-
};
|
|
57
54
|
Throttler.prototype.setDelayMs = function (delayMs) {
|
|
58
55
|
this.delayMs = delayMs;
|
|
59
56
|
};
|
|
@@ -64,22 +61,27 @@ var Throttler = /** @class */ (function () {
|
|
|
64
61
|
Throttler.prototype.run = function () {
|
|
65
62
|
var _a, _b, _c, _d;
|
|
66
63
|
return __awaiter(this, void 0, void 0, function () {
|
|
67
|
-
var fn, result, err_1;
|
|
64
|
+
var countRunning, fn, decrementTimeout, result, err_1;
|
|
68
65
|
var _this = this;
|
|
69
66
|
return __generator(this, function (_e) {
|
|
70
67
|
switch (_e.label) {
|
|
71
68
|
case 0:
|
|
72
|
-
|
|
69
|
+
countRunning = this.decrementTimeouts.size;
|
|
70
|
+
if (countRunning >= this.maxConcurrent) {
|
|
73
71
|
return [2 /*return*/];
|
|
74
72
|
}
|
|
75
73
|
if (this.queue.length === 0) {
|
|
76
|
-
if (
|
|
74
|
+
if (countRunning === 0) {
|
|
77
75
|
(_a = this.onEnd) === null || _a === void 0 ? void 0 : _a.call(this, this.results, this.errors);
|
|
78
76
|
}
|
|
79
77
|
return [2 /*return*/];
|
|
80
78
|
}
|
|
81
|
-
this.countRunning++;
|
|
82
79
|
fn = this.queue.shift();
|
|
80
|
+
decrementTimeout = setTimeout(function () {
|
|
81
|
+
_this.decrementTimeouts.delete(decrementTimeout);
|
|
82
|
+
_this.run();
|
|
83
|
+
}, this.delayMs);
|
|
84
|
+
this.decrementTimeouts.add(decrementTimeout);
|
|
83
85
|
_e.label = 1;
|
|
84
86
|
case 1:
|
|
85
87
|
_e.trys.push([1, 3, , 4]);
|
|
@@ -95,12 +97,10 @@ var Throttler = /** @class */ (function () {
|
|
|
95
97
|
(_c = this.onError) === null || _c === void 0 ? void 0 : _c.call(this, err_1);
|
|
96
98
|
return [3 /*break*/, 4];
|
|
97
99
|
case 4:
|
|
98
|
-
this.countRunning--;
|
|
99
100
|
(_d = this.onProgress) === null || _d === void 0 ? void 0 : _d.call(this, {
|
|
100
101
|
queueLength: this.queue.length,
|
|
101
|
-
countRunning: this.
|
|
102
|
+
countRunning: this.decrementTimeouts.size,
|
|
102
103
|
});
|
|
103
|
-
setTimeout(function () { return _this.run(); }, this.delayMs);
|
|
104
104
|
return [2 /*return*/];
|
|
105
105
|
}
|
|
106
106
|
});
|
package/package.json
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sec-edgar-api",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Fetch and parse SEC earnings reports and other filings. Useful for financial analysis.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"author": "Andrew Evers (https://github.com/andyevers)",
|
|
7
7
|
"homepage": "https://github.com/andyevers/sec-edgar-api#readme",
|
|
8
8
|
"license": "ISC",
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"unzipper": "^0.10.14"
|
|
11
|
-
},
|
|
12
9
|
"repository": {
|
|
13
10
|
"type": "git",
|
|
14
11
|
"url": "git+https://github.com/andyevers/sec-edgar-api.git"
|
|
15
12
|
},
|
|
16
13
|
"scripts": {
|
|
17
14
|
"test": "jest test",
|
|
18
|
-
"build": "tsc"
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"publish": "npm run build && npm publish"
|
|
19
17
|
},
|
|
20
18
|
"keywords": [
|
|
21
19
|
"sec",
|
|
@@ -27,6 +25,9 @@
|
|
|
27
25
|
"earnings",
|
|
28
26
|
"reports"
|
|
29
27
|
],
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"unzipper": "^0.10.14"
|
|
30
|
+
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@types/jest": "^29.5.2",
|
|
32
33
|
"@types/unzipper": "^0.10.6",
|