@invinite-org/invinite-data-cli 0.1.19

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 (93) hide show
  1. package/README.md +693 -0
  2. package/claude-plugin/.claude-plugin/plugin.json +11 -0
  3. package/claude-plugin/agents/invinite-data.md +46 -0
  4. package/claude-plugin/commands/financial-research.md +69 -0
  5. package/claude-plugin/skills/invinite-data-cli/SKILL.md +251 -0
  6. package/dist/bin/invd.d.ts +2 -0
  7. package/dist/bin/invd.js +5 -0
  8. package/dist/bin/invd.js.map +1 -0
  9. package/dist/src/cli.d.ts +2 -0
  10. package/dist/src/cli.js +47 -0
  11. package/dist/src/cli.js.map +1 -0
  12. package/dist/src/client/api-client.d.ts +6 -0
  13. package/dist/src/client/api-client.js +40 -0
  14. package/dist/src/client/api-client.js.map +1 -0
  15. package/dist/src/client/pagination.d.ts +3 -0
  16. package/dist/src/client/pagination.js +27 -0
  17. package/dist/src/client/pagination.js.map +1 -0
  18. package/dist/src/client/websocket-client.d.ts +1 -0
  19. package/dist/src/client/websocket-client.js +57 -0
  20. package/dist/src/client/websocket-client.js.map +1 -0
  21. package/dist/src/commands/company.d.ts +2 -0
  22. package/dist/src/commands/company.js +220 -0
  23. package/dist/src/commands/company.js.map +1 -0
  24. package/dist/src/commands/config.d.ts +2 -0
  25. package/dist/src/commands/config.js +56 -0
  26. package/dist/src/commands/config.js.map +1 -0
  27. package/dist/src/commands/filings.d.ts +2 -0
  28. package/dist/src/commands/filings.js +139 -0
  29. package/dist/src/commands/filings.js.map +1 -0
  30. package/dist/src/commands/financials.d.ts +2 -0
  31. package/dist/src/commands/financials.js +162 -0
  32. package/dist/src/commands/financials.js.map +1 -0
  33. package/dist/src/commands/health.d.ts +2 -0
  34. package/dist/src/commands/health.js +18 -0
  35. package/dist/src/commands/health.js.map +1 -0
  36. package/dist/src/commands/insider-trades.d.ts +2 -0
  37. package/dist/src/commands/insider-trades.js +56 -0
  38. package/dist/src/commands/insider-trades.js.map +1 -0
  39. package/dist/src/commands/ipos.d.ts +2 -0
  40. package/dist/src/commands/ipos.js +42 -0
  41. package/dist/src/commands/ipos.js.map +1 -0
  42. package/dist/src/commands/market.d.ts +2 -0
  43. package/dist/src/commands/market.js +34 -0
  44. package/dist/src/commands/market.js.map +1 -0
  45. package/dist/src/commands/metadata.d.ts +2 -0
  46. package/dist/src/commands/metadata.js +39 -0
  47. package/dist/src/commands/metadata.js.map +1 -0
  48. package/dist/src/commands/metrics.d.ts +2 -0
  49. package/dist/src/commands/metrics.js +158 -0
  50. package/dist/src/commands/metrics.js.map +1 -0
  51. package/dist/src/commands/ownership.d.ts +2 -0
  52. package/dist/src/commands/ownership.js +152 -0
  53. package/dist/src/commands/ownership.js.map +1 -0
  54. package/dist/src/commands/plugin.d.ts +2 -0
  55. package/dist/src/commands/plugin.js +303 -0
  56. package/dist/src/commands/plugin.js.map +1 -0
  57. package/dist/src/commands/segments.d.ts +2 -0
  58. package/dist/src/commands/segments.js +64 -0
  59. package/dist/src/commands/segments.js.map +1 -0
  60. package/dist/src/commands/ws.d.ts +2 -0
  61. package/dist/src/commands/ws.js +14 -0
  62. package/dist/src/commands/ws.js.map +1 -0
  63. package/dist/src/config/auth.d.ts +2 -0
  64. package/dist/src/config/auth.js +70 -0
  65. package/dist/src/config/auth.js.map +1 -0
  66. package/dist/src/config/config-manager.d.ts +6 -0
  67. package/dist/src/config/config-manager.js +37 -0
  68. package/dist/src/config/config-manager.js.map +1 -0
  69. package/dist/src/formatters/json-formatter.d.ts +1 -0
  70. package/dist/src/formatters/json-formatter.js +4 -0
  71. package/dist/src/formatters/json-formatter.js.map +1 -0
  72. package/dist/src/formatters/table-formatter.d.ts +3 -0
  73. package/dist/src/formatters/table-formatter.js +63 -0
  74. package/dist/src/formatters/table-formatter.js.map +1 -0
  75. package/dist/src/formatters/tree-formatter.d.ts +11 -0
  76. package/dist/src/formatters/tree-formatter.js +30 -0
  77. package/dist/src/formatters/tree-formatter.js.map +1 -0
  78. package/dist/src/shared/errors.d.ts +6 -0
  79. package/dist/src/shared/errors.js +32 -0
  80. package/dist/src/shared/errors.js.map +1 -0
  81. package/dist/src/shared/options.d.ts +13 -0
  82. package/dist/src/shared/options.js +14 -0
  83. package/dist/src/shared/options.js.map +1 -0
  84. package/dist/src/shared/output.d.ts +3 -0
  85. package/dist/src/shared/output.js +13 -0
  86. package/dist/src/shared/output.js.map +1 -0
  87. package/dist/src/shared/spinner.d.ts +3 -0
  88. package/dist/src/shared/spinner.js +12 -0
  89. package/dist/src/shared/spinner.js.map +1 -0
  90. package/dist/src/shared/types.d.ts +11 -0
  91. package/dist/src/shared/types.js +2 -0
  92. package/dist/src/shared/types.js.map +1 -0
  93. package/package.json +54 -0
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: invinite-data
3
+ description: Fetches financial data from the Invinite Data API for analysis. Use this agent whenever you need company financials, SEC filings, institutional ownership, insider trades, financial ratios, growth metrics, or any stock/company data. Delegate to this agent when the user asks for financial data retrieval, company research, or comparative financial analysis — even if they don't mention "Invinite" explicitly. This agent knows how to efficiently query the right endpoints, combine data from multiple sources, and return structured results ready for analysis.
4
+ tools: Bash(invd *), Read, Glob, Grep
5
+ skills:
6
+ - invinite-data-cli
7
+ model: sonnet
8
+ ---
9
+
10
+ # Invinite Data Agent
11
+
12
+ You are a financial data retrieval specialist. Your job is to fetch the requested data from the Invinite Data API using the `invd` CLI and return it in a clean, structured format ready for analysis.
13
+
14
+ ## How you work
15
+
16
+ 1. **Parse the request** — understand what data the user needs (which companies, what type of data, what time period)
17
+ 2. **Plan the queries** — determine which `invd` CLI commands to run. Prefer fewer, broader queries over many narrow ones. Use the snapshot endpoint when comparing multiple companies.
18
+ 3. **Fetch the data** — run the CLI commands with `--json` flag. Always use `--json` for machine-readable output.
19
+ 4. **Return structured results** — present the data clearly. If multiple queries were needed, combine the results into a coherent response.
20
+
21
+ ## Important rules
22
+
23
+ - Always use `--json` on every data command
24
+ - **Before querying metrics (ratios, CAGR, or growth) or financial statements, first run `invd metadata metrics --json`** to discover the available metric identifiers. The responses from these endpoints use `metric_id` keys — you need the metadata to know what metrics exist and to correctly interpret the results. Run this as a first step alongside or before your main data queries.
25
+ - **Before querying filing sections, first run `invd metadata section-ids --json`** to discover valid section IDs.
26
+ - If a command fails with an authentication error, report it clearly and tell the caller that `INVINITE_DATA_API_KEY` must be set or `invd config set-key` must be run
27
+ - If a company identifier is ambiguous, use `invd company search -q "<name>" --json` first to resolve it
28
+ - For comparing companies, prefer `invd financials snapshot -i AAPL,MSFT,GOOGL -p annual --json` over individual queries
29
+ - When fetching financial statements, default to `annual` period unless the request specifies otherwise
30
+ - Use `--limit` appropriately — don't fetch more data than needed, but don't under-fetch either
31
+ - For large datasets, use `--all` only when specifically needed
32
+
33
+ ## Query planning
34
+
35
+ When the request involves multiple data types (e.g., "get me Apple's financials and who owns it"), run the commands in parallel where possible rather than sequentially.
36
+
37
+ Common multi-step patterns:
38
+ - **Company research**: metadata metrics (first) + company details + financials snapshot + metrics ratios
39
+ - **Metrics analysis**: metadata metrics (first) → then ratios/CAGR/growth queries
40
+ - **Ownership analysis**: holdings-by-company + ownership transactions
41
+ - **Filing deep-dive**: metadata section-ids (first) + filings list → then filings sections for full text
42
+ - **Comparative analysis**: metadata metrics (first) + financials snapshot with multiple tickers + metrics ratios for each
43
+
44
+ ## Output format
45
+
46
+ Return the raw JSON data. Do not summarize or interpret — the caller (or the user's main conversation) will handle analysis. If the data is very large, note the total count and return the most relevant subset.
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: financial-research
3
+ description: Perform AI-powered financial research and analysis. Use when the user asks to research companies, compare financials, analyze ownership patterns, review SEC filings, evaluate growth trends, or any multi-faceted financial question. This command orchestrates parallel data fetching and then synthesizes the results into a coherent analysis.
4
+ argument-hint: [question or research topic]
5
+ ---
6
+
7
+ # Financial Research
8
+
9
+ You are a financial research orchestrator. The user has asked you to research or analyze financial data. Your job is to break the question into parallel data retrieval tasks, spawn `invinite-data` subagents to fetch the data concurrently, and then synthesize the results into a clear, insightful analysis.
10
+
11
+ ## Step 1: Decompose the question
12
+
13
+ Break the user's request into independent data retrieval tasks. Think about what data sources you need:
14
+
15
+ - **Company fundamentals**: company details, financial snapshots
16
+ - **Metrics & ratios**: profitability, valuation, liquidity, solvency ratios, CAGR, growth rates
17
+ - **Statements**: income statements, balance sheets, cash flows (for trend analysis)
18
+ - **Ownership**: institutional holders, ownership transactions, insider trades
19
+ - **Filings**: SEC filing sections (risk factors, MD&A, business descriptions)
20
+ - **Context**: dividends, stock splits, fiscal periods, segments
21
+
22
+ Each independent data need becomes a separate subagent task.
23
+
24
+ ## Step 2: Spawn invinite-data subagents in parallel
25
+
26
+ Launch all data retrieval tasks at the same time using the `invinite-data` agent. Each subagent gets a focused prompt describing exactly what data to fetch.
27
+
28
+ **Example**: if the user asks "Compare Apple and Microsoft's financial health", spawn subagents in parallel like:
29
+
30
+ 1. `invinite-data`: "Fetch the latest annual financial snapshot for AAPL and MSFT"
31
+ 2. `invinite-data`: "Fetch profitability and liquidity ratios for AAPL, annual period"
32
+ 3. `invinite-data`: "Fetch profitability and liquidity ratios for MSFT, annual period"
33
+ 4. `invinite-data`: "Fetch 5-year CAGR metrics for AAPL and MSFT"
34
+
35
+ **Key rules for spawning:**
36
+ - Always spawn as many subagents in parallel as possible — do not fetch sequentially
37
+ - Give each subagent a specific, focused task — one clear data request per agent
38
+ - If the user mentions companies by name (not ticker), include "resolve the ticker first" in the subagent prompt
39
+ - For comparative analysis, consider fetching data for all companies in a single snapshot call rather than one per company
40
+
41
+ ## Step 3: Analyze and synthesize
42
+
43
+ Once all subagents return their data, combine the results into a structured analysis:
44
+
45
+ 1. **Present key findings first** — lead with the most important insights
46
+ 2. **Use tables for comparisons** — side-by-side metrics are easier to read than prose
47
+ 3. **Highlight notable patterns** — trends, outliers, divergences between companies
48
+ 4. **Provide context** — explain what the numbers mean, not just what they are
49
+ 5. **Flag data gaps** — if any subagent couldn't fetch data, note what's missing and why
50
+
51
+ ## Output format
52
+
53
+ Structure your analysis with clear sections. Adapt the structure to the question, but a typical research output might look like:
54
+
55
+ ```
56
+ ## Summary
57
+ [2-3 sentence executive summary]
58
+
59
+ ## Key Metrics
60
+ [Table comparing the most relevant data points]
61
+
62
+ ## Analysis
63
+ [Deeper discussion of trends, comparisons, and insights]
64
+
65
+ ## Considerations
66
+ [Risks, caveats, or areas for further research]
67
+ ```
68
+
69
+ Keep the analysis focused on what the user asked. Don't pad with irrelevant data just because it was fetched.
@@ -0,0 +1,251 @@
1
+ ---
2
+ name: invinite-data-cli
3
+ description: Fetch financial data using the Invinite Data API CLI. Use this skill whenever the user wants to look up company information, financial statements, SEC filings, institutional ownership, insider trades, IPO data, market holidays, financial metrics, or any stock/company-related data. Also use when the user mentions tickers, CIKs, balance sheets, income statements, cash flows, 10-K, 10-Q, ratios, CAGR, growth rates, dividends, stock splits, or institutional holdings — even if they don't mention "Invinite" by name.
4
+ allowed-tools: Bash(invd *)
5
+ ---
6
+
7
+ # Invinite Data API CLI
8
+
9
+ The `invd` CLI provides access to comprehensive financial data from the Invinite Data API. Always use `--json` when fetching data for analysis — it returns structured JSON you can pipe to `jq` or parse programmatically.
10
+
11
+ ## Prerequisites
12
+
13
+ The CLI must be installed (`npm install -g @invinite-org/invinite-data-cli`) and authenticated. Authentication is resolved in this order:
14
+ 1. `INVINITE_DATA_API_KEY` environment variable
15
+ 2. OS keychain (via optional `keytar`)
16
+ 3. Stored config (set via `invd config set-key`)
17
+
18
+ If a command fails with an auth error, tell the user to run `invd config set-key` or set `INVINITE_DATA_API_KEY`.
19
+
20
+ ## Global Options
21
+
22
+ | Flag | Description |
23
+ |------|-------------|
24
+ | `--json` | Output raw JSON (always use this for programmatic access) |
25
+ | `--all` | Auto-paginate through all results |
26
+
27
+ ## Commands Reference
28
+
29
+ ### Company Data
30
+
31
+ ```bash
32
+ # List all companies
33
+ invd company list --json
34
+
35
+ # Search by ticker or name
36
+ invd company search -q "Apple" --json
37
+ invd company search -q MSFT --limit 5 --json
38
+
39
+ # Company details (ticker or CIK)
40
+ invd company details -i AAPL --json
41
+
42
+ # Dividends (with optional date range)
43
+ invd company dividends -i AAPL --json
44
+ invd company dividends -i AAPL --start-date 2023-01-01 --end-date 2024-01-01 --json
45
+
46
+ # Fiscal periods
47
+ invd company fiscal-periods -i MSFT --json
48
+
49
+ # Stock splits
50
+ invd company splits -i AAPL --json
51
+ ```
52
+
53
+ ### Financial Statements
54
+
55
+ Period is required: `quarterly`, `annual`, `ytd`, or `ttm`.
56
+
57
+ Financial statement responses use standardized `metric_id` keys (from `metadata metrics`) as field names. If you need to understand what a specific metric_id means, check `invd metadata metrics --json` first.
58
+
59
+ ```bash
60
+ # Income statement
61
+ invd financials income-statement -i AAPL -p annual --json
62
+ invd financials income-statement -i AAPL -p quarterly --limit 4 --json
63
+
64
+ # Balance sheet
65
+ invd financials balance-sheet -i MSFT -p quarterly --limit 4 --json
66
+
67
+ # Cash flow statement
68
+ invd financials cash-flow -i GOOGL -p annual --json
69
+
70
+ # Financial snapshot (multiple companies, comma-separated)
71
+ invd financials snapshot -i AAPL,MSFT,GOOGL -p annual --json
72
+ invd financials snapshot -i AAPL -p quarterly --calendar-year 2024 --calendar-quarter 3 --json
73
+ ```
74
+
75
+ Statement options:
76
+ - `--detailed` — includes formula, accession number, HTML tag info
77
+ - `--presentation` — returns nested tree structure (hierarchical)
78
+ - `--as-reported` — uses as-reported data instead of standardized
79
+ - `--with-formula` — includes formula info (requires `--detailed`)
80
+ - `--detailed` and `--presentation` are mutually exclusive
81
+
82
+ ### Financial Metrics
83
+
84
+ **Before querying any metrics endpoint (ratios, CAGR, or growth), first fetch the available metric identifiers using `metadata metrics`.** The response from ratios/CAGR/growth uses `metric_id` keys (e.g., `PR_TO_EARNINGS`, `CURRENT_RATIO`) — without knowing the available IDs, you won't know what data exists or how to interpret the results. This also helps you confirm that the metric the user is asking about actually exists.
85
+
86
+ ```bash
87
+ # STEP 1: Always fetch available metrics first
88
+ invd metadata metrics --json
89
+ # Returns: { metrics: [{ metric_id: "...", name: "..." }, ...] }
90
+ # Use this to understand what metric_id keys appear in ratios/CAGR/growth responses
91
+
92
+ # STEP 2: Then query the specific metrics endpoint
93
+ # Ratios (categories: valuation, profitability, liquidity, solvency)
94
+ invd metrics ratios -i AAPL -p annual --json
95
+ invd metrics ratios -i AAPL -p annual --category profitability --json
96
+
97
+ # CAGR (periods: 3, 5, or 10 years)
98
+ invd metrics cagr -i AAPL --json
99
+ invd metrics cagr -i AAPL --period-years 5 --json
100
+
101
+ # Growth metrics (year_over_year or quarter_over_quarter)
102
+ invd metrics growth -i MSFT -p quarterly --growth-type year_over_year --json
103
+ ```
104
+
105
+ The metrics response structures differ by endpoint:
106
+ - **Ratios**: `period.facts[category][metric_id]` — organized by category (valuation, profitability, etc.)
107
+ - **CAGR**: `period.facts[years][metric_id]` — organized by time period (3-year, 5-year, 10-year)
108
+ - **Growth**: `period.facts[growthType][metric_id]` — organized by growth type (year_over_year, quarter_over_quarter)
109
+
110
+ All share the same `metric_id` identifiers from `metadata metrics`.
111
+
112
+ ### Segments
113
+
114
+ ```bash
115
+ # Segmented financials
116
+ invd segments list -i AAPL -p annual --json
117
+ invd segments list -i AAPL -p annual --detailed --json
118
+ ```
119
+
120
+ ### SEC Filings
121
+
122
+ ```bash
123
+ # List filings (filter by form type: 10-K, 10-Q, 8-K, etc.)
124
+ invd filings list -i AAPL --json
125
+ invd filings list -i AAPL --form-type 10-K --json
126
+
127
+ # Natural language search through filings
128
+ invd filings search -r "revenue recognition policy changes" -i AAPL --json
129
+
130
+ # Fetch filing sections (full text content)
131
+ invd filings sections -i AAPL --form-type 10-K --section-id risk_factors --json
132
+ invd filings sections -i AAPL --form-type 10-K --accession-number 0000320193-23-000106 --json
133
+
134
+ # Available form types
135
+ invd filings form-types --json
136
+ invd filings form-types -i AAPL --json
137
+
138
+ # Available section IDs
139
+ invd metadata section-ids --json
140
+ ```
141
+
142
+ ### Institutional Ownership
143
+
144
+ ```bash
145
+ # Holdings by investor (requires CIK)
146
+ invd ownership holdings-by-investor --cik 0001067983 --json
147
+
148
+ # Holdings by company
149
+ invd ownership holdings-by-company -i AAPL --json
150
+ invd ownership holdings-by-company -i AAPL --min-value 1000000 --json
151
+
152
+ # Ownership transactions
153
+ invd ownership transactions -i AAPL --type new_buy --json
154
+ invd ownership transactions --cik 0001067983 --calendar-year 2024 --json
155
+
156
+ # List institutional investors
157
+ invd ownership institutions --json
158
+ invd ownership institutions --ciks 0001067983,0001364742 --json
159
+ ```
160
+
161
+ Transaction types: `new_buy`, `added`, `reduced`, `sold_out`
162
+
163
+ ### Insider Trades
164
+
165
+ ```bash
166
+ # Insider transactions
167
+ invd insider-trades list -i AAPL --json
168
+ invd insider-trades list -i TSLA --acquired-disposed D --limit 20 --json
169
+ invd insider-trades list -i AAPL --start-date 2024-01-01 --json
170
+ ```
171
+
172
+ `--acquired-disposed`: `A` (acquisition) or `D` (disposition)
173
+
174
+ ### IPOs
175
+
176
+ ```bash
177
+ invd ipos list --json
178
+ invd ipos list --start-date 2024-01-01 --end-date 2024-12-31 --json
179
+ ```
180
+
181
+ ### Market Data
182
+
183
+ ```bash
184
+ invd market holidays --json
185
+ ```
186
+
187
+ ### Metadata (query before using metrics or filing sections)
188
+
189
+ These are discovery endpoints — use them before querying data that depends on specific identifiers.
190
+
191
+ ```bash
192
+ # List all available metric IDs — run this BEFORE querying ratios, CAGR, or growth
193
+ invd metadata metrics --json
194
+ # Returns: { metrics: [{ metric_id: "PR_TO_EARNINGS", name: "Price-to-Earnings Ratio" }, ...] }
195
+
196
+ # List available section IDs — run this BEFORE querying filing sections
197
+ invd metadata section-ids --json
198
+ ```
199
+
200
+ ### Health Check
201
+
202
+ ```bash
203
+ invd health --json
204
+ ```
205
+
206
+ ## Pagination
207
+
208
+ All list endpoints support:
209
+ - `-l, --limit <n>` — max results per page
210
+ - `--offset <n>` — pagination offset
211
+ - `--all` — auto-paginate all results
212
+ - `-s, --sort <dir>` — `asc` or `desc`
213
+
214
+ ## Common Patterns
215
+
216
+ ### Comparing companies
217
+ Fetch snapshots for multiple tickers at once:
218
+ ```bash
219
+ invd financials snapshot -i AAPL,MSFT,GOOGL -p annual --json
220
+ ```
221
+
222
+ ### Getting the latest quarterly data
223
+ ```bash
224
+ invd financials income-statement -i AAPL -p quarterly --limit 1 --json
225
+ ```
226
+
227
+ ### Finding who owns a stock
228
+ ```bash
229
+ invd ownership holdings-by-company -i AAPL --min-value 10000000 --json
230
+ ```
231
+
232
+ ### Searching SEC filings by topic
233
+ ```bash
234
+ invd filings search -r "artificial intelligence strategy" -i MSFT --json
235
+ ```
236
+
237
+ ### Reading specific filing sections
238
+ First find section IDs, then fetch the section:
239
+ ```bash
240
+ invd metadata section-ids --json
241
+ invd filings sections -i AAPL --form-type 10-K --section-id risk_factors --json
242
+ ```
243
+
244
+ ## Tips
245
+
246
+ - Always use `--json` for data you'll analyze or transform
247
+ - Use `--all` cautiously — some endpoints return thousands of results
248
+ - Company identifiers accept both ticker symbols (AAPL) and CIK numbers
249
+ - For financial statements, `annual` gives the full year, `quarterly` gives each quarter, `ttm` gives trailing twelve months, `ytd` gives year-to-date
250
+ - The `snapshot` command is the most efficient way to get complete financials for one or more companies at once
251
+ - Filing sections return full text — great for detailed analysis of risk factors, MD&A, business descriptions, etc.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { createProgram } from '../src/cli.js';
3
+ const program = createProgram();
4
+ program.parse();
5
+ //# sourceMappingURL=invd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invd.js","sourceRoot":"","sources":["../../bin/invd.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createProgram(): Command;
@@ -0,0 +1,47 @@
1
+ import { Command } from 'commander';
2
+ import { setJsonMode } from './shared/spinner.js';
3
+ import { registerConfigCommands } from './commands/config.js';
4
+ import { registerHealthCommand } from './commands/health.js';
5
+ import { registerCompanyCommands } from './commands/company.js';
6
+ import { registerFinancialsCommands } from './commands/financials.js';
7
+ import { registerMetricsCommands } from './commands/metrics.js';
8
+ import { registerSegmentsCommands } from './commands/segments.js';
9
+ import { registerIposCommands } from './commands/ipos.js';
10
+ import { registerOwnershipCommands } from './commands/ownership.js';
11
+ import { registerInsiderTradesCommands } from './commands/insider-trades.js';
12
+ import { registerFilingsCommands } from './commands/filings.js';
13
+ import { registerMarketCommands } from './commands/market.js';
14
+ import { registerMetadataCommands } from './commands/metadata.js';
15
+ import { registerWsCommands } from './commands/ws.js';
16
+ import { registerPluginCommands } from './commands/plugin.js';
17
+ export function createProgram() {
18
+ const program = new Command();
19
+ program
20
+ .name('invd')
21
+ .description('CLI for the Invinite financial data API')
22
+ .version('0.1.0')
23
+ .option('--json', 'Output raw JSON (pipe-friendly)')
24
+ .option('--all', 'Auto-paginate through all results')
25
+ .hook('preAction', (thisCommand) => {
26
+ const opts = thisCommand.opts();
27
+ if (opts.json) {
28
+ setJsonMode(true);
29
+ }
30
+ });
31
+ registerConfigCommands(program);
32
+ registerHealthCommand(program);
33
+ registerCompanyCommands(program);
34
+ registerFinancialsCommands(program);
35
+ registerMetricsCommands(program);
36
+ registerSegmentsCommands(program);
37
+ registerIposCommands(program);
38
+ registerOwnershipCommands(program);
39
+ registerInsiderTradesCommands(program);
40
+ registerFilingsCommands(program);
41
+ registerMarketCommands(program);
42
+ registerMetadataCommands(program);
43
+ registerWsCommands(program);
44
+ registerPluginCommands(program);
45
+ return program;
46
+ }
47
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,yCAAyC,CAAC;SACtD,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;SACnD,MAAM,CAAC,OAAO,EAAE,mCAAmC,CAAC;SACpD,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACpC,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACnC,6BAA6B,CAAC,OAAO,CAAC,CAAC;IACvC,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface RequestOptions {
2
+ path: string;
3
+ params?: Record<string, string | undefined>;
4
+ silent?: boolean;
5
+ }
6
+ export declare function apiGet<T = unknown>(opts: RequestOptions): Promise<T>;
@@ -0,0 +1,40 @@
1
+ import { getApiKey } from '../config/auth.js';
2
+ import { getBaseUrl } from '../config/config-manager.js';
3
+ import { ApiError } from '../shared/errors.js';
4
+ import { createSpinner } from '../shared/spinner.js';
5
+ function buildUrl(path, params) {
6
+ const base = getBaseUrl().replace(/\/+$/, '');
7
+ const url = new URL(`${base}${path}`);
8
+ if (params) {
9
+ for (const [key, value] of Object.entries(params)) {
10
+ if (value !== undefined && value !== '') {
11
+ url.searchParams.set(key, value);
12
+ }
13
+ }
14
+ }
15
+ return url.toString();
16
+ }
17
+ export async function apiGet(opts) {
18
+ const spinner = opts.silent ? null : createSpinner('Fetching data...');
19
+ try {
20
+ const apiKey = await getApiKey();
21
+ const url = buildUrl(opts.path, opts.params);
22
+ const response = await fetch(url, {
23
+ headers: {
24
+ 'Authorization': `Bearer ${apiKey}`,
25
+ 'Accept': 'application/json',
26
+ },
27
+ });
28
+ const body = await response.json();
29
+ if (!response.ok) {
30
+ throw new ApiError(response.status, body?.error || 'Unknown Error', body?.message || `Request failed with status ${response.status}`);
31
+ }
32
+ spinner?.succeed('Done');
33
+ return body;
34
+ }
35
+ catch (error) {
36
+ spinner?.fail('Failed');
37
+ throw error;
38
+ }
39
+ }
40
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/client/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAQrD,SAAS,QAAQ,CAAC,IAAY,EAAE,MAA2C;IACzE,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;IACtC,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAc,IAAoB;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,MAAM,EAAE;gBACnC,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAS,CAAC;QAE1C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,QAAQ,CAChB,QAAQ,CAAC,MAAM,EACf,IAAI,EAAE,KAAK,IAAI,eAAe,EAC9B,IAAI,EAAE,OAAO,IAAI,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CACjE,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,IAAS,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ type NextUrlExtractor<T> = (data: T) => string | undefined;
2
+ export declare function fetchAllPages<T>(initialData: T, extractNextUrl: NextUrlExtractor<T>, mergeResults: (accumulated: T, page: T) => T): Promise<T>;
3
+ export {};
@@ -0,0 +1,27 @@
1
+ import { apiGet } from './api-client.js';
2
+ import { createSpinner } from '../shared/spinner.js';
3
+ export async function fetchAllPages(initialData, extractNextUrl, mergeResults) {
4
+ let result = initialData;
5
+ let nextUrl = extractNextUrl(result);
6
+ let page = 1;
7
+ while (nextUrl) {
8
+ page++;
9
+ const spinner = createSpinner(`Fetching page ${page}...`);
10
+ try {
11
+ // nextUrl is absolute, extract path+query
12
+ const url = new URL(nextUrl);
13
+ const params = {};
14
+ url.searchParams.forEach((v, k) => { params[k] = v; });
15
+ const pageData = await apiGet({ path: url.pathname, params, silent: true });
16
+ result = mergeResults(result, pageData);
17
+ nextUrl = extractNextUrl(pageData);
18
+ spinner.succeed(`Page ${page} fetched`);
19
+ }
20
+ catch (error) {
21
+ spinner.fail(`Page ${page} failed`);
22
+ throw error;
23
+ }
24
+ }
25
+ return result;
26
+ }
27
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../../src/client/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAc,EACd,cAAmC,EACnC,YAA4C;IAE5C,IAAI,MAAM,GAAG,WAAW,CAAC;IACzB,IAAI,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,EAAE,CAAC;QACP,MAAM,OAAO,GAAG,aAAa,CAAC,iBAAiB,IAAI,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC;YACH,0CAA0C;YAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7B,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAI,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/E,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACxC,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC;YACpC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function connectWebSocket(): Promise<void>;
@@ -0,0 +1,57 @@
1
+ import { getApiKey } from '../config/auth.js';
2
+ import { getBaseUrl } from '../config/config-manager.js';
3
+ import chalk from 'chalk';
4
+ export async function connectWebSocket() {
5
+ const apiKey = await getApiKey();
6
+ const base = getBaseUrl().replace(/\/+$/, '').replace(/^http/, 'ws');
7
+ const url = `${base}/v1/ws?api_key=${encodeURIComponent(apiKey)}`;
8
+ let reconnectDelay = 1000;
9
+ let shouldReconnect = true;
10
+ function connect() {
11
+ console.log(chalk.dim('Connecting to WebSocket...'));
12
+ const ws = new WebSocket(url);
13
+ ws.addEventListener('open', () => {
14
+ console.log(chalk.green('Connected to filing stream'));
15
+ reconnectDelay = 1000;
16
+ });
17
+ ws.addEventListener('message', (event) => {
18
+ try {
19
+ const data = JSON.parse(String(event.data));
20
+ if (data.type === 'ping')
21
+ return;
22
+ if (data.type === 'new_filing') {
23
+ const f = data.filing;
24
+ console.log(chalk.bold(`[${f.form_type}]`) + ` ${f.cik} - Filed ${f.filing_date}`);
25
+ if (f.html_url)
26
+ console.log(chalk.dim(` ${f.html_url}`));
27
+ }
28
+ else {
29
+ console.log(JSON.stringify(data, null, 2));
30
+ }
31
+ }
32
+ catch {
33
+ console.log(String(event.data));
34
+ }
35
+ });
36
+ ws.addEventListener('close', () => {
37
+ if (shouldReconnect) {
38
+ console.log(chalk.yellow(`Disconnected. Reconnecting in ${reconnectDelay / 1000}s...`));
39
+ setTimeout(connect, reconnectDelay);
40
+ reconnectDelay = Math.min(reconnectDelay * 2, 30000);
41
+ }
42
+ });
43
+ ws.addEventListener('error', (error) => {
44
+ console.error(chalk.red('WebSocket error:'), error);
45
+ });
46
+ process.on('SIGINT', () => {
47
+ shouldReconnect = false;
48
+ ws.close();
49
+ console.log(chalk.dim('\nDisconnected.'));
50
+ process.exit(0);
51
+ });
52
+ }
53
+ connect();
54
+ // Keep process alive
55
+ await new Promise(() => { });
56
+ }
57
+ //# sourceMappingURL=websocket-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../../../src/client/websocket-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerCompanyCommands(program: Command): void;