@civiq/entity-resolution 0.1.0

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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/data/bioguide-fec-mapping.json +4186 -0
  4. package/data/sec-sic-data.json +10427 -0
  5. package/dist/__tests__/company-entity-resolver.test.d.ts +6 -0
  6. package/dist/__tests__/company-entity-resolver.test.d.ts.map +1 -0
  7. package/dist/__tests__/company-entity-resolver.test.js +267 -0
  8. package/dist/__tests__/company-entity-resolver.test.js.map +1 -0
  9. package/dist/__tests__/entity-resolution.test.d.ts +2 -0
  10. package/dist/__tests__/entity-resolution.test.d.ts.map +1 -0
  11. package/dist/__tests__/entity-resolution.test.js +296 -0
  12. package/dist/__tests__/entity-resolution.test.js.map +1 -0
  13. package/dist/__tests__/fec-entity-resolution.test.d.ts +2 -0
  14. package/dist/__tests__/fec-entity-resolution.test.d.ts.map +1 -0
  15. package/dist/__tests__/fec-entity-resolution.test.js +49 -0
  16. package/dist/__tests__/fec-entity-resolution.test.js.map +1 -0
  17. package/dist/bioguide-fec-mapping.d.ts +27 -0
  18. package/dist/bioguide-fec-mapping.d.ts.map +1 -0
  19. package/dist/bioguide-fec-mapping.js +57 -0
  20. package/dist/bioguide-fec-mapping.js.map +1 -0
  21. package/dist/cache.d.ts +18 -0
  22. package/dist/cache.d.ts.map +1 -0
  23. package/dist/cache.js +18 -0
  24. package/dist/cache.js.map +1 -0
  25. package/dist/committee-agency-map.d.ts +58 -0
  26. package/dist/committee-agency-map.d.ts.map +1 -0
  27. package/dist/committee-agency-map.js +658 -0
  28. package/dist/committee-agency-map.js.map +1 -0
  29. package/dist/committee-alias-table.d.ts +11 -0
  30. package/dist/committee-alias-table.d.ts.map +1 -0
  31. package/dist/committee-alias-table.js +191 -0
  32. package/dist/committee-alias-table.js.map +1 -0
  33. package/dist/company-alias-table.d.ts +36 -0
  34. package/dist/company-alias-table.d.ts.map +1 -0
  35. package/dist/company-alias-table.js +1307 -0
  36. package/dist/company-alias-table.js.map +1 -0
  37. package/dist/company-entity-resolver.d.ts +94 -0
  38. package/dist/company-entity-resolver.d.ts.map +1 -0
  39. package/dist/company-entity-resolver.js +282 -0
  40. package/dist/company-entity-resolver.js.map +1 -0
  41. package/dist/configure.d.ts +15 -0
  42. package/dist/configure.d.ts.map +1 -0
  43. package/dist/configure.js +19 -0
  44. package/dist/configure.js.map +1 -0
  45. package/dist/fec-entity-resolution.d.ts +88 -0
  46. package/dist/fec-entity-resolution.d.ts.map +1 -0
  47. package/dist/fec-entity-resolution.js +407 -0
  48. package/dist/fec-entity-resolution.js.map +1 -0
  49. package/dist/index.d.ts +30 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +33 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/industry-taxonomy.d.ts +90 -0
  54. package/dist/industry-taxonomy.d.ts.map +1 -0
  55. package/dist/industry-taxonomy.js +1026 -0
  56. package/dist/industry-taxonomy.js.map +1 -0
  57. package/dist/lda-issue-policy-map.d.ts +13 -0
  58. package/dist/lda-issue-policy-map.d.ts.map +1 -0
  59. package/dist/lda-issue-policy-map.js +193 -0
  60. package/dist/lda-issue-policy-map.js.map +1 -0
  61. package/dist/lobbying-committee-resolver.d.ts +23 -0
  62. package/dist/lobbying-committee-resolver.d.ts.map +1 -0
  63. package/dist/lobbying-committee-resolver.js +158 -0
  64. package/dist/lobbying-committee-resolver.js.map +1 -0
  65. package/dist/logger.d.ts +20 -0
  66. package/dist/logger.d.ts.map +1 -0
  67. package/dist/logger.js +20 -0
  68. package/dist/logger.js.map +1 -0
  69. package/dist/sic-sector-map.d.ts +32 -0
  70. package/dist/sic-sector-map.d.ts.map +1 -0
  71. package/dist/sic-sector-map.js +109 -0
  72. package/dist/sic-sector-map.js.map +1 -0
  73. package/dist/ticker-industry-resolver.d.ts +22 -0
  74. package/dist/ticker-industry-resolver.d.ts.map +1 -0
  75. package/dist/ticker-industry-resolver.js +254 -0
  76. package/dist/ticker-industry-resolver.js.map +1 -0
  77. package/dist/types.d.ts +30 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +6 -0
  80. package/dist/types.js.map +1 -0
  81. package/package.json +51 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Copyright (c) 2019-2025 Mark Sandford
3
+ * Licensed under the MIT License. See LICENSE and NOTICE files.
4
+ */
5
+ /**
6
+ * SIC Code to IndustrySector Mapping
7
+ *
8
+ * Maps Standard Industrial Classification (SIC) code ranges to the
9
+ * IndustrySector enum from src/lib/fec/industry-taxonomy.ts.
10
+ *
11
+ * SIC codes are 4-digit numbers organized into divisions:
12
+ * 0100-0999: Agriculture, Forestry, Fishing
13
+ * 1000-1499: Mining
14
+ * 1500-1799: Construction
15
+ * 2000-3999: Manufacturing
16
+ * 4000-4999: Transportation, Communications, Utilities
17
+ * 5000-5199: Wholesale Trade
18
+ * 5200-5999: Retail Trade
19
+ * 6000-6799: Finance, Insurance, Real Estate
20
+ * 7000-8999: Services
21
+ * 9100-9999: Public Administration
22
+ *
23
+ * Some ranges are further subdivided to match the OpenSecrets-style
24
+ * 13-sector model used across CIV.IQ.
25
+ */
26
+ import { IndustrySector } from './industry-taxonomy';
27
+ /**
28
+ * Ordered list of SIC code ranges mapped to IndustrySector.
29
+ * More specific ranges precede broader ones.
30
+ */
31
+ const SIC_RANGES = [
32
+ // Agriculture, Forestry, Fishing (0100-0999)
33
+ { start: 100, end: 999, sector: IndustrySector.AGRIBUSINESS },
34
+ // Mining (1000-1499) — Energy/Natural Resources
35
+ { start: 1000, end: 1499, sector: IndustrySector.ENERGY_NATURAL_RESOURCES },
36
+ // Construction (1500-1799)
37
+ { start: 1500, end: 1799, sector: IndustrySector.CONSTRUCTION },
38
+ // Manufacturing — Food products (2000-2099) → Agribusiness
39
+ { start: 2000, end: 2099, sector: IndustrySector.AGRIBUSINESS },
40
+ // Manufacturing — Tobacco, Textiles, Wood, Paper, Printing (2100-2799) → Misc Business
41
+ { start: 2100, end: 2799, sector: IndustrySector.MISC_BUSINESS },
42
+ // Manufacturing — Chemicals, Pharmaceuticals (2800-2899) → Health
43
+ { start: 2800, end: 2899, sector: IndustrySector.HEALTH },
44
+ // Manufacturing — Petroleum refining, Rubber, Plastics (2900-3099) → Energy
45
+ { start: 2900, end: 3099, sector: IndustrySector.ENERGY_NATURAL_RESOURCES },
46
+ // Manufacturing — Stone, Clay, Glass, Primary Metals, Fabricated Metals (3100-3499) → Misc Business
47
+ { start: 3100, end: 3499, sector: IndustrySector.MISC_BUSINESS },
48
+ // Manufacturing — Industrial machinery, Computers (3500-3599) → Communications/Electronics
49
+ { start: 3500, end: 3599, sector: IndustrySector.COMMUNICATIONS_ELECTRONICS },
50
+ // Manufacturing — Electronic components, Semiconductors (3600-3699) → Communications/Electronics
51
+ { start: 3600, end: 3699, sector: IndustrySector.COMMUNICATIONS_ELECTRONICS },
52
+ // Manufacturing — Transportation equipment (3700-3799) → Transportation
53
+ { start: 3700, end: 3719, sector: IndustrySector.TRANSPORTATION },
54
+ // Manufacturing — Aircraft, Guided missiles, Space vehicles (3720-3799) → Defense
55
+ { start: 3720, end: 3799, sector: IndustrySector.DEFENSE },
56
+ // Manufacturing — Instruments, Medical devices (3800-3899) → Health
57
+ { start: 3800, end: 3899, sector: IndustrySector.HEALTH },
58
+ // Manufacturing — Misc manufacturing (3900-3999) → Misc Business
59
+ { start: 3900, end: 3999, sector: IndustrySector.MISC_BUSINESS },
60
+ // Transportation — Railroad, Trucking, Water, Air (4000-4599) → Transportation
61
+ { start: 4000, end: 4599, sector: IndustrySector.TRANSPORTATION },
62
+ // Transportation — Pipelines (4600-4699) → Energy
63
+ { start: 4600, end: 4699, sector: IndustrySector.ENERGY_NATURAL_RESOURCES },
64
+ // Communications — Telephone, Radio, TV, Cable (4700-4899) → Communications/Electronics
65
+ { start: 4700, end: 4899, sector: IndustrySector.COMMUNICATIONS_ELECTRONICS },
66
+ // Utilities — Electric, Gas, Water, Sanitary (4900-4999) → Energy
67
+ { start: 4900, end: 4999, sector: IndustrySector.ENERGY_NATURAL_RESOURCES },
68
+ // Wholesale Trade (5000-5199) → Misc Business
69
+ { start: 5000, end: 5199, sector: IndustrySector.MISC_BUSINESS },
70
+ // Retail Trade (5200-5999) → Misc Business
71
+ { start: 5200, end: 5999, sector: IndustrySector.MISC_BUSINESS },
72
+ // Finance, Insurance, Real Estate (6000-6797)
73
+ { start: 6000, end: 6797, sector: IndustrySector.FINANCE_INSURANCE_REAL_ESTATE },
74
+ // Services — Hotels, Personal services (7000-7299) → Misc Business
75
+ { start: 7000, end: 7299, sector: IndustrySector.MISC_BUSINESS },
76
+ // Services — Business services, Computer programming (7300-7399) → Communications/Electronics
77
+ { start: 7300, end: 7399, sector: IndustrySector.COMMUNICATIONS_ELECTRONICS },
78
+ // Services — Auto repair, Misc repair, Entertainment (7400-7999) → Misc Business
79
+ { start: 7400, end: 7999, sector: IndustrySector.MISC_BUSINESS },
80
+ // Services — Health services (8000-8099) → Health
81
+ { start: 8000, end: 8099, sector: IndustrySector.HEALTH },
82
+ // Services — Legal services (8100-8199) → Lawyers & Lobbyists
83
+ { start: 8100, end: 8199, sector: IndustrySector.LAWYERS_LOBBYISTS },
84
+ // Services — Education (8200-8299) → Ideology/Single-Issue
85
+ { start: 8200, end: 8299, sector: IndustrySector.IDEOLOGY_SINGLE_ISSUE },
86
+ // Services — Social services, Museums, Membership orgs (8300-8699) → Ideology/Single-Issue
87
+ { start: 8300, end: 8699, sector: IndustrySector.IDEOLOGY_SINGLE_ISSUE },
88
+ // Services — Engineering, Accounting, Research, Management (8700-8999) → Misc Business
89
+ { start: 8700, end: 8999, sector: IndustrySector.MISC_BUSINESS },
90
+ // Public Administration (9100-9999) → Other
91
+ { start: 9100, end: 9999, sector: IndustrySector.OTHER },
92
+ ];
93
+ /**
94
+ * Resolve a 4-digit SIC code string to an IndustrySector.
95
+ * Returns null if the code is invalid or falls outside all known ranges.
96
+ */
97
+ export function sicToSector(sicCode) {
98
+ const code = parseInt(sicCode, 10);
99
+ if (isNaN(code) || code < 100 || code > 9999) {
100
+ return null;
101
+ }
102
+ for (const range of SIC_RANGES) {
103
+ if (code >= range.start && code <= range.end) {
104
+ return range.sector;
105
+ }
106
+ }
107
+ return null;
108
+ }
109
+ //# sourceMappingURL=sic-sector-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sic-sector-map.js","sourceRoot":"","sources":["../src/sic-sector-map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright (c) 2019-2025 Mark Sandford
3
+ * Licensed under the MIT License. See LICENSE and NOTICE files.
4
+ */
5
+ import type { TickerResolution } from './types';
6
+ /**
7
+ * Resolve a stock ticker to an IndustrySector.
8
+ *
9
+ * Returns null for ETFs, mutual funds, and tickers that can't be resolved.
10
+ * Uses Redis caching for SEC API responses (30-day TTL).
11
+ */
12
+ export declare function resolveTickerIndustry(ticker: string): Promise<TickerResolution | null>;
13
+ /**
14
+ * Resolve multiple stock tickers to IndustrySectors in parallel.
15
+ *
16
+ * Deduplicates tickers, checks cache in batch, then resolves remaining
17
+ * tickers concurrently (max 5 parallel SEC API requests).
18
+ *
19
+ * Returns a Map from normalized ticker to resolution (null for unresolvable).
20
+ */
21
+ export declare function resolveTickerIndustries(tickers: string[]): Promise<Map<string, TickerResolution | null>>;
22
+ //# sourceMappingURL=ticker-industry-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticker-industry-resolver.d.ts","sourceRoot":"","sources":["../src/ticker-industry-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAsDhD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAiE5F;AAqCD;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAqD/C"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Copyright (c) 2019-2025 Mark Sandford
3
+ * Licensed under the MIT License. See LICENSE and NOTICE files.
4
+ */
5
+ /**
6
+ * Ticker-to-Industry Resolver
7
+ *
8
+ * Resolves stock tickers from House Clerk disclosure filings to
9
+ * IndustrySector using SEC EDGAR data + SIC code mapping.
10
+ *
11
+ * Flow: ticker → CIK (static lookup) → SIC code (SEC API, cached) → IndustrySector
12
+ *
13
+ * ETFs, mutual funds, and unresolvable tickers return null.
14
+ */
15
+ import { getLogger } from './logger';
16
+ import { getCache } from './cache';
17
+ import { sicToSector } from './sic-sector-map';
18
+ // Static ticker → CIK mapping from SEC EDGAR company_tickers.json
19
+ // ~10K entries, ~155KB
20
+ import tickerCikMap from '../data/sec-sic-data.json';
21
+ /** SIC code cache TTL: 30 days (SIC codes rarely change) */
22
+ const SIC_CACHE_TTL = 30 * 24 * 60 * 60;
23
+ /** SEC EDGAR submissions API base URL */
24
+ const SEC_SUBMISSIONS_URL = 'https://data.sec.gov/submissions';
25
+ /** SEC requires a User-Agent header identifying the requester */
26
+ const SEC_USER_AGENT = 'CIV.IQ civic-intel-hub/1.0 (civdotiq.org)';
27
+ /**
28
+ * Known ETF/fund tickers that should return null (no single sector).
29
+ * This is not exhaustive — the resolver also returns null for tickers
30
+ * not found in the SEC company data.
31
+ */
32
+ const KNOWN_FUNDS = new Set([
33
+ 'SPY',
34
+ 'QQQ',
35
+ 'IWM',
36
+ 'DIA',
37
+ 'VTI',
38
+ 'VOO',
39
+ 'VEA',
40
+ 'VWO',
41
+ 'EFA',
42
+ 'AGG',
43
+ 'BND',
44
+ 'TLT',
45
+ 'GLD',
46
+ 'SLV',
47
+ 'USO',
48
+ 'XLF',
49
+ 'XLE',
50
+ 'XLK',
51
+ 'XLV',
52
+ 'XLI',
53
+ 'XLP',
54
+ 'XLY',
55
+ 'XLB',
56
+ 'XLU',
57
+ 'XLRE',
58
+ 'XLC',
59
+ 'ARKK',
60
+ 'ARKW',
61
+ 'ARKG',
62
+ 'ARKF',
63
+ 'ARKQ',
64
+ ]);
65
+ /**
66
+ * Resolve a stock ticker to an IndustrySector.
67
+ *
68
+ * Returns null for ETFs, mutual funds, and tickers that can't be resolved.
69
+ * Uses Redis caching for SEC API responses (30-day TTL).
70
+ */
71
+ export async function resolveTickerIndustry(ticker) {
72
+ const normalizedTicker = ticker.toUpperCase().trim();
73
+ if (!normalizedTicker) {
74
+ return null;
75
+ }
76
+ // Skip known funds/ETFs
77
+ if (KNOWN_FUNDS.has(normalizedTicker)) {
78
+ return null;
79
+ }
80
+ // Check Redis cache first
81
+ const cacheKey = `ticker-sic:${normalizedTicker}`;
82
+ try {
83
+ const cached = await getCache().get(cacheKey);
84
+ if (cached === 'null') {
85
+ return null;
86
+ }
87
+ if (cached) {
88
+ return cached;
89
+ }
90
+ }
91
+ catch {
92
+ // Cache miss or error — continue to resolution
93
+ }
94
+ // Look up CIK from static data
95
+ const cik = tickerCikMap[normalizedTicker];
96
+ if (!cik) {
97
+ getLogger().debug(`[TickerResolver] No CIK found for ticker: ${normalizedTicker}`);
98
+ await cacheMiss(cacheKey);
99
+ return null;
100
+ }
101
+ // Fetch SIC code from SEC EDGAR API
102
+ const sicCode = await fetchSicCode(cik);
103
+ if (!sicCode) {
104
+ await cacheMiss(cacheKey);
105
+ return null;
106
+ }
107
+ // Map SIC code to IndustrySector
108
+ const sector = sicToSector(sicCode);
109
+ if (!sector) {
110
+ getLogger().debug(`[TickerResolver] SIC ${sicCode} has no sector mapping for ${normalizedTicker}`);
111
+ await cacheMiss(cacheKey);
112
+ return null;
113
+ }
114
+ const result = {
115
+ sector,
116
+ sicCode,
117
+ confidence: 1.0,
118
+ };
119
+ // Cache successful resolution
120
+ try {
121
+ await getCache().set(cacheKey, result, SIC_CACHE_TTL);
122
+ }
123
+ catch {
124
+ // Cache write failure is non-fatal
125
+ }
126
+ return result;
127
+ }
128
+ /**
129
+ * Fetch SIC code from SEC EDGAR submissions API.
130
+ * The CIK is zero-padded to 10 digits per SEC convention.
131
+ */
132
+ async function fetchSicCode(cik) {
133
+ const paddedCik = String(cik).padStart(10, '0');
134
+ const url = `${SEC_SUBMISSIONS_URL}/CIK${paddedCik}.json`;
135
+ try {
136
+ const response = await fetch(url, {
137
+ headers: { 'User-Agent': SEC_USER_AGENT },
138
+ signal: AbortSignal.timeout(10000),
139
+ });
140
+ if (!response.ok) {
141
+ getLogger().warn(`[TickerResolver] SEC API returned ${response.status} for CIK ${cik}`);
142
+ return null;
143
+ }
144
+ const data = await response.json();
145
+ const sic = data?.sic;
146
+ if (!sic) {
147
+ return null;
148
+ }
149
+ return String(sic);
150
+ }
151
+ catch (error) {
152
+ getLogger().error('[TickerResolver] SEC API fetch failed', error, {
153
+ cik: String(cik),
154
+ });
155
+ return null;
156
+ }
157
+ }
158
+ /**
159
+ * Resolve multiple stock tickers to IndustrySectors in parallel.
160
+ *
161
+ * Deduplicates tickers, checks cache in batch, then resolves remaining
162
+ * tickers concurrently (max 5 parallel SEC API requests).
163
+ *
164
+ * Returns a Map from normalized ticker to resolution (null for unresolvable).
165
+ */
166
+ export async function resolveTickerIndustries(tickers) {
167
+ const results = new Map();
168
+ // Deduplicate and normalize
169
+ const uniqueTickers = [...new Set(tickers.map(t => t.toUpperCase().trim()).filter(Boolean))];
170
+ if (uniqueTickers.length === 0) {
171
+ return results;
172
+ }
173
+ // Separate known funds (instant null)
174
+ const resolvable = [];
175
+ for (const ticker of uniqueTickers) {
176
+ if (KNOWN_FUNDS.has(ticker)) {
177
+ results.set(ticker, null);
178
+ }
179
+ else {
180
+ resolvable.push(ticker);
181
+ }
182
+ }
183
+ // Batch cache lookup
184
+ const cacheKeys = resolvable.map(t => `ticker-sic:${t}`);
185
+ const cached = await Promise.all(cacheKeys.map(key => getCache()
186
+ .get(key)
187
+ .catch(() => null)));
188
+ const uncached = [];
189
+ for (let i = 0; i < resolvable.length; i++) {
190
+ const hit = cached[i];
191
+ if (hit === 'null') {
192
+ results.set(resolvable[i], null);
193
+ }
194
+ else if (hit) {
195
+ results.set(resolvable[i], hit);
196
+ }
197
+ else {
198
+ uncached.push(resolvable[i]);
199
+ }
200
+ }
201
+ // Resolve uncached tickers with concurrency limit
202
+ const CONCURRENCY = 5;
203
+ for (let i = 0; i < uncached.length; i += CONCURRENCY) {
204
+ const batch = uncached.slice(i, i + CONCURRENCY);
205
+ const resolved = await Promise.all(batch.map(t => resolveSingle(t)));
206
+ for (let j = 0; j < batch.length; j++) {
207
+ results.set(batch[j], resolved[j]);
208
+ }
209
+ }
210
+ return results;
211
+ }
212
+ /**
213
+ * Resolve a single ticker (no cache check — used by batch after cache miss).
214
+ */
215
+ async function resolveSingle(normalizedTicker) {
216
+ const cacheKey = `ticker-sic:${normalizedTicker}`;
217
+ const cik = tickerCikMap[normalizedTicker];
218
+ if (!cik) {
219
+ getLogger().debug(`[TickerResolver] No CIK found for ticker: ${normalizedTicker}`);
220
+ await cacheMiss(cacheKey);
221
+ return null;
222
+ }
223
+ const sicCode = await fetchSicCode(cik);
224
+ if (!sicCode) {
225
+ await cacheMiss(cacheKey);
226
+ return null;
227
+ }
228
+ const sector = sicToSector(sicCode);
229
+ if (!sector) {
230
+ getLogger().debug(`[TickerResolver] SIC ${sicCode} has no sector mapping for ${normalizedTicker}`);
231
+ await cacheMiss(cacheKey);
232
+ return null;
233
+ }
234
+ const result = { sector, sicCode, confidence: 1.0 };
235
+ try {
236
+ await getCache().set(cacheKey, result, SIC_CACHE_TTL);
237
+ }
238
+ catch {
239
+ // Non-fatal
240
+ }
241
+ return result;
242
+ }
243
+ /**
244
+ * Cache a null result to avoid repeated lookups for unresolvable tickers.
245
+ */
246
+ async function cacheMiss(cacheKey) {
247
+ try {
248
+ await getCache().set(cacheKey, 'null', SIC_CACHE_TTL);
249
+ }
250
+ catch {
251
+ // Non-fatal
252
+ }
253
+ }
254
+ //# sourceMappingURL=ticker-industry-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ticker-industry-resolver.js","sourceRoot":"","sources":["../src/ticker-industry-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2019-2025 Mark Sandford
3
+ * Licensed under the MIT License. See LICENSE and NOTICE files.
4
+ */
5
+ import type { IndustrySector } from './industry-taxonomy';
6
+ /** Result of resolving a single LDA government_entities string. */
7
+ export interface GovernmentEntityResolution {
8
+ /** Original text from the LDA filing. */
9
+ rawText: string;
10
+ /** Resolution outcome. */
11
+ type: 'committee' | 'agency' | 'noise' | 'unresolved';
12
+ /** Committee code (e.g., "SSFI") if resolved to a committee. */
13
+ committeeCode?: string;
14
+ /** Committee name if resolved. */
15
+ committeeName?: string;
16
+ /** Agency slug if resolved to an agency. */
17
+ agencySlug?: string;
18
+ /** Resolution confidence: 1.0 for exact, 0.85+ for fuzzy, 0 for noise. */
19
+ confidence: number;
20
+ }
21
+ /**
22
+ * Result of resolving a stock ticker to an industry sector.
23
+ * Returns null for ETFs, mutual funds, and unresolvable tickers.
24
+ */
25
+ export interface TickerResolution {
26
+ sector: IndustrySector;
27
+ sicCode: string;
28
+ confidence: number;
29
+ }
30
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,mEAAmE;AACnE,MAAM,WAAW,0BAA0B;IACzC,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;IACtD,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) 2019-2025 Mark Sandford
3
+ * Licensed under the MIT License. See LICENSE and NOTICE files.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@civiq/entity-resolution",
3
+ "version": "0.1.0",
4
+ "description": "Entity resolution for civic data — committee/agency alias matching, industry taxonomy, ticker-to-sector resolution, FEC entity deduplication",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./industry-taxonomy": {
14
+ "types": "./dist/industry-taxonomy.d.ts",
15
+ "import": "./dist/industry-taxonomy.js"
16
+ },
17
+ "./committee-agency-map": {
18
+ "types": "./dist/committee-agency-map.d.ts",
19
+ "import": "./dist/committee-agency-map.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "data"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc",
28
+ "test": "vitest run",
29
+ "clean": "rm -rf dist"
30
+ },
31
+ "dependencies": {
32
+ "fuse.js": "^7.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "typescript": "^5.8.0"
36
+ },
37
+ "license": "MIT",
38
+ "author": "Mark Sandford",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/civiq/entity-resolution"
42
+ },
43
+ "keywords": [
44
+ "entity-resolution",
45
+ "civic",
46
+ "government",
47
+ "committee",
48
+ "fec",
49
+ "civic-tech"
50
+ ]
51
+ }