sec-edgar-api 1.0.5 → 1.0.7

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.
@@ -30,7 +30,7 @@ export default class ReportRawBuilder {
30
30
  createFacts(companyFacts: CompanyFactListData, includeNamePrefix?: boolean): {
31
31
  facts: FactItem[];
32
32
  };
33
- private getFactKey;
33
+ getFactKey(fact: FactItem, pathSeparator: string): string;
34
34
  buildReports(params: BuildReportsParams): ReportRaw[];
35
35
  private createReportKey;
36
36
  private createReport;
@@ -1,4 +1,17 @@
1
1
  import { XbrlLinkbase } from '../types/xbrl.type';
2
+ export declare function getLabelsByTypeByTaxonomy(labelLinkbase: XbrlLinkbase): Record<string, Record<string, string>>;
3
+ /**
4
+ * The primary label based on priority: verboseLabel > terseLabel > label > periodEndLabel > first available label (excluding periodStartLabel)
5
+ *
6
+ * @param labelsByType The result of getLabelsByTypeByTaxonomy[key]
7
+ */
8
+ export declare function getPrimaryLabel(labelsByType: Record<string, string>): string;
9
+ /**
10
+ * The primary documentation based on priority: documentation > longest available label
11
+ *
12
+ * @param labelsByType The result of getLabelsByTypeByTaxonomy[key]
13
+ */
14
+ export declare function getPrimaryDocumentation(labelsByType: Record<string, string>): string;
2
15
  /**
3
16
  * Gets labels by taxonomy from the label linkbase. priority level: verboseLabel > terseLabel > label.
4
17
  */
@@ -1,40 +1,99 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTaxonomyFromId = exports.getLabelByTaxonomy = void 0;
4
- /**
5
- * Gets labels by taxonomy from the label linkbase. priority level: verboseLabel > terseLabel > label.
6
- */
7
- function getLabelByTaxonomy(labelLinkbase) {
3
+ exports.getTaxonomyFromId = exports.getLabelByTaxonomy = exports.getPrimaryDocumentation = exports.getPrimaryLabel = exports.getLabelsByTypeByTaxonomy = void 0;
4
+ function getLabelsByTypeByTaxonomy(labelLinkbase) {
8
5
  var _a;
9
- var labelByTaxonomy = {};
10
- var taxonomyWithVerboseLabels = new Set();
11
- (_a = labelLinkbase.labelLink) === null || _a === void 0 ? void 0 : _a.forEach(function (link) {
6
+ var labelsByTypeByTaxonomy = {};
7
+ (_a = labelLinkbase === null || labelLinkbase === void 0 ? void 0 : labelLinkbase.labelLink) === null || _a === void 0 ? void 0 : _a.forEach(function (link) {
12
8
  var _a;
13
9
  (_a = link.label) === null || _a === void 0 ? void 0 : _a.forEach(function (_a) {
14
- var _b = _a.label, label = _b === void 0 ? '' : _b, _c = _a.text, text = _c === void 0 ? '' : _c, _d = _a.role, role = _d === void 0 ? '' : _d;
10
+ var _b;
11
+ var _c = _a.label, label = _c === void 0 ? '' : _c, _d = _a.text, text = _d === void 0 ? '' : _d, _e = _a.role, role = _e === void 0 ? '' : _e;
15
12
  var taxonomy = getTaxonomyFromId(label);
16
- // skip if verbose label already exists for this taxonomy
17
- if (taxonomyWithVerboseLabels.has(taxonomy)) {
18
- return;
19
- }
20
- // label, terseLabel, or verboseLabel
21
13
  var labelType = role.substring(role.lastIndexOf('/') + 1);
22
- // skip periodStartLabel. Used for beginning cash position, but overwrites end cash position.
23
- if (labelType === 'periodStartLabel') {
24
- return;
25
- }
26
- if (labelType === 'verboseLabel') {
27
- taxonomyWithVerboseLabels.add(taxonomy);
28
- }
29
- // prefer terseLabel over regular label
30
- if (!labelByTaxonomy[taxonomy] || labelType === 'terseLabel' || labelType === 'verboseLabel') {
31
- labelByTaxonomy[taxonomy] = text;
32
- }
14
+ (_b = labelsByTypeByTaxonomy[taxonomy]) !== null && _b !== void 0 ? _b : (labelsByTypeByTaxonomy[taxonomy] = {});
15
+ labelsByTypeByTaxonomy[taxonomy][labelType] = text;
33
16
  });
34
17
  });
18
+ return labelsByTypeByTaxonomy;
19
+ }
20
+ exports.getLabelsByTypeByTaxonomy = getLabelsByTypeByTaxonomy;
21
+ /**
22
+ * The primary label based on priority: verboseLabel > terseLabel > label > periodEndLabel > first available label (excluding periodStartLabel)
23
+ *
24
+ * @param labelsByType The result of getLabelsByTypeByTaxonomy[key]
25
+ */
26
+ function getPrimaryLabel(labelsByType) {
27
+ var _a, _b;
28
+ var preferredLabel = labelsByType.verboseLabel || labelsByType.terseLabel || labelsByType.label || labelsByType.periodEndLabel;
29
+ if (preferredLabel)
30
+ return preferredLabel;
31
+ // return the first available label that is not periodStartLabel
32
+ return (_b = (_a = Object.entries(labelsByType).find(function (_a) {
33
+ var k = _a[0], v = _a[1];
34
+ return k !== 'periodStartLabel' && v.length > 0;
35
+ })) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : '';
36
+ }
37
+ exports.getPrimaryLabel = getPrimaryLabel;
38
+ /**
39
+ * The primary documentation based on priority: documentation > longest available label
40
+ *
41
+ * @param labelsByType The result of getLabelsByTypeByTaxonomy[key]
42
+ */
43
+ function getPrimaryDocumentation(labelsByType) {
44
+ if (labelsByType.documentation)
45
+ return labelsByType.documentation;
46
+ var validKeys = Object.keys(labelsByType).filter(function (key) { return key !== 'periodStartLabel'; });
47
+ return validKeys.reduce(function (acc, curr) { return (acc.length > curr.length ? acc : curr); }, '');
48
+ }
49
+ exports.getPrimaryDocumentation = getPrimaryDocumentation;
50
+ /**
51
+ * Gets labels by taxonomy from the label linkbase. priority level: verboseLabel > terseLabel > label.
52
+ */
53
+ function getLabelByTaxonomy(labelLinkbase) {
54
+ var labelByTaxonomy = {};
55
+ var labelsByTypeByTaxonomy = getLabelsByTypeByTaxonomy(labelLinkbase);
56
+ for (var taxonomy in labelsByTypeByTaxonomy) {
57
+ labelByTaxonomy[taxonomy] = getPrimaryLabel(labelsByTypeByTaxonomy[taxonomy]);
58
+ }
35
59
  return labelByTaxonomy;
36
60
  }
37
61
  exports.getLabelByTaxonomy = getLabelByTaxonomy;
62
+ // /**
63
+ // * Gets labels by taxonomy from the label linkbase. priority level: verboseLabel > terseLabel > label.
64
+ // */
65
+ // export function getDefinitionByTaxonomy(definitionLinkbase: XbrlLinkbase) {
66
+ // const labelByTaxonomy: Record<string, string> = {}
67
+ // const taxonomyWithVerboseLabels = new Set<string>()
68
+ // definitionLinkbase.definitionLink?.forEach((link) => {
69
+ // link.definitionArc?.forEach(({ }) => {
70
+ // const taxonomy = getTaxonomyFromId(definition)
71
+ // // skip if verbose label already exists for this taxonomy
72
+ // if (taxonomyWithVerboseLabels.has(taxonomy)) {
73
+ // return
74
+ // }
75
+ // // label, terseLabel, or verboseLabel
76
+ // const labelType = role.substring(role.lastIndexOf('/') + 1) as
77
+ // | 'label'
78
+ // | 'terseLabel'
79
+ // | 'verboseLabel'
80
+ // | 'periodStartLabel'
81
+ // | 'periodEndLabel'
82
+ // // skip periodStartLabel. Used for beginning cash position, but overwrites end cash position.
83
+ // if (labelType === 'periodStartLabel') {
84
+ // return
85
+ // }
86
+ // if (labelType === 'verboseLabel') {
87
+ // taxonomyWithVerboseLabels.add(taxonomy)
88
+ // }
89
+ // // prefer terseLabel over regular label
90
+ // if (!labelByTaxonomy[taxonomy] || labelType === 'terseLabel' || labelType === 'verboseLabel') {
91
+ // labelByTaxonomy[taxonomy] = text
92
+ // }
93
+ // })
94
+ // })
95
+ // return labelByTaxonomy
96
+ // }
38
97
  function isPascaleCase(str) {
39
98
  var startsWithUpperCase = str && str[0].toLowerCase() !== str[0];
40
99
  return startsWithUpperCase && str.split('').some(function (c) { return c.toLowerCase() === c; });
@@ -51,6 +110,21 @@ function getTaxonomyFromId(id) {
51
110
  var isLabelIndicatorPosition3 = parts[2] === 'lbl';
52
111
  var isKnownPrefixPosition1 = knownPrefixes[parts[0]] === true;
53
112
  var isNameInPosition2 = parts.length <= 2 || isLabelIndicatorPosition3 || isKnownPrefixPosition1 || isPascaleCase(parts[1]);
54
- return isNameInPosition2 ? parts.slice(0, 2).join(':') : parts.slice(1, 3).join(':');
113
+ var result = isNameInPosition2 ? parts.slice(0, 2).join(':') : parts.slice(1, 3).join(':');
114
+ // this happens when the prefix is touching the concept name like "loc_us-gaapAssetsCurrent_lab".
115
+ // The symbol "GAN" has this issue.
116
+ if (result.startsWith('loc:')) {
117
+ var idWithoutLoc_1 = id.substring(4);
118
+ var knownPrefix = Object.keys(knownPrefixes).find(function (prefix) { return idWithoutLoc_1.startsWith(prefix); });
119
+ if (knownPrefix) {
120
+ return "".concat(knownPrefix, ":").concat(idWithoutLoc_1.substring(knownPrefix.length).split('_')[0]);
121
+ }
122
+ // custom taxonomy, assume the first capital letter followed by a lowercase is the concept name. ex: GANAssetsCurrentCustomConcept.match(/([A-Z][a-z]+)/)
123
+ var indexUpperFollowedByLower = idWithoutLoc_1.search(/[a-z]/) - 1;
124
+ var customPrefix = idWithoutLoc_1.substring(0, indexUpperFollowedByLower);
125
+ var conceptName = idWithoutLoc_1.substring(indexUpperFollowedByLower).split('_')[0];
126
+ return "".concat(customPrefix, ":").concat(conceptName.replace(/'|"/g, ''));
127
+ }
128
+ return result.replace(/'|"/g, '');
55
129
  }
56
130
  exports.getTaxonomyFromId = getTaxonomyFromId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sec-edgar-api",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
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)",