@invinite-org/invinite-data-cli 0.1.20 → 0.1.22
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 +40 -3
- package/claude-plugin/.claude-plugin/plugin.json +12 -4
- package/claude-plugin/.mcp.json +8 -0
- package/claude-plugin/agents/invinite-data.md +1 -1
- package/claude-plugin/commands/analyze-filing.md +15 -0
- package/claude-plugin/commands/compare-companies.md +15 -0
- package/claude-plugin/commands/ownership-review.md +14 -0
- package/claude-plugin/skills/invinite-data-cli/SKILL.md +38 -8
- package/dist/src/cli.js +2 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/login.d.ts +18 -0
- package/dist/src/commands/login.js +252 -0
- package/dist/src/commands/login.js.map +1 -0
- package/dist/src/config/auth.d.ts +7 -0
- package/dist/src/config/auth.js +22 -7
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config-manager.d.ts +1 -0
- package/dist/src/config/config-manager.js +3 -0
- package/dist/src/config/config-manager.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,11 +30,33 @@ Requires Node.js >= 20.
|
|
|
30
30
|
|
|
31
31
|
## Authentication
|
|
32
32
|
|
|
33
|
-
The
|
|
33
|
+
The recommended way to authenticate is browser login:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
invd login
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The browser flow creates a revocable, 90-day Data API key and stores it in the
|
|
40
|
+
OS keychain when available (with local CLI config as a fallback). The sign-in
|
|
41
|
+
also appears in the web UI's Data API key settings. If you belong to multiple
|
|
42
|
+
teams, choose one explicitly:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
invd login --team <teamId>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To revoke the browser sign-in and remove the locally stored credential:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
invd logout
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Manual API keys remain supported. The active key is resolved in the following order:
|
|
34
55
|
|
|
35
56
|
1. **Environment variable** — `INVINITE_DATA_API_KEY`
|
|
36
|
-
2. **
|
|
37
|
-
3. **
|
|
57
|
+
2. **Current directory `.env` file** — `INVINITE_DATA_API_KEY=...`
|
|
58
|
+
3. **OS keychain** — via the optional `keytar` package
|
|
59
|
+
4. **Stored config** — set with the CLI
|
|
38
60
|
|
|
39
61
|
### Set your API key
|
|
40
62
|
|
|
@@ -48,10 +70,21 @@ You'll be prompted to enter your key (input is masked). Alternatively, export it
|
|
|
48
70
|
export INVINITE_DATA_API_KEY=your-api-key
|
|
49
71
|
```
|
|
50
72
|
|
|
73
|
+
Because environment and `.env` values take precedence over stored credentials,
|
|
74
|
+
`invd logout` will tell you to remove them manually when either is active.
|
|
75
|
+
|
|
51
76
|
## AI Plugin
|
|
52
77
|
|
|
53
78
|
This repo includes plugins for AI coding tools that enable AI-powered financial data retrieval and analysis. Supports **Claude Code**, **OpenCode**, **Codex**, and **Copilot**.
|
|
54
79
|
|
|
80
|
+
### Choose an integration
|
|
81
|
+
|
|
82
|
+
- **Standalone skill:** installs the Invinite workflow and CLI reference. It prefers MCP when connected and falls back to the local `invd` CLI.
|
|
83
|
+
- **Standalone MCP connector:** add `https://data.invinite.com/t/<teamId>/mcp` in Claude's connector settings, leave OAuth client ID/secret empty, and complete browser OAuth. This supplies tools but not the packaged research workflows.
|
|
84
|
+
- **Claude plugin:** bundles the skill, remote MCP connector, data agent, and research commands. During setup, enter the team ID shown in the team-pinned MCP URL in Invinite Data API settings; OAuth still uses Dynamic Client Registration and PKCE.
|
|
85
|
+
|
|
86
|
+
The team ID controls access, usage, and billing for MCP calls. CLI calls use the team selected by `invd login --team <teamId>` and do not inherit the plugin's connector setting.
|
|
87
|
+
|
|
55
88
|
### Quick install
|
|
56
89
|
|
|
57
90
|
```bash
|
|
@@ -98,6 +131,8 @@ npx @invinite-org/invinite-data-cli@latest plugin uninstall --all --global
|
|
|
98
131
|
claude --plugin-dir /path/to/invinite-data-cli/claude-plugin
|
|
99
132
|
```
|
|
100
133
|
|
|
134
|
+
The Claude plugin also includes `compare-companies`, `analyze-filing`, and `ownership-review`. Its `.mcp.json` connects the team-pinned remote server automatically; use `/mcp` to complete OAuth or inspect connection status in Claude Code. In Claude web/Desktop, install the plugin through your organization's plugin marketplace, enter the team ID when prompted, and connect the bundled connector.
|
|
135
|
+
|
|
101
136
|
### Usage examples
|
|
102
137
|
|
|
103
138
|
Use `/financial-research` for multi-step analysis:
|
|
@@ -123,6 +158,8 @@ These options are available on all data commands:
|
|
|
123
158
|
|
|
124
159
|
## Commands
|
|
125
160
|
|
|
161
|
+
- `login` — Log in through your browser (`--team <teamId>` for multi-team users)
|
|
162
|
+
- `logout` — Revoke the current browser sign-in and clear local credentials
|
|
126
163
|
- [config](#config) — Manage CLI configuration
|
|
127
164
|
- [health](#health) — Check API health
|
|
128
165
|
- [company](#company) — Company information
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "invinite-financial-data",
|
|
3
3
|
"description": "Fetch and analyze financial data using the Invinite Data API — company fundamentals, financial statements, SEC filings, institutional ownership, insider trades, and more.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"author": {
|
|
6
|
-
"name": "
|
|
6
|
+
"name": "Invinite"
|
|
7
7
|
},
|
|
8
8
|
"homepage": "https://github.com/outraday-org/invinite-data-cli",
|
|
9
9
|
"repository": "https://github.com/outraday-org/invinite-data-cli",
|
|
10
|
-
"license": "ISC"
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"userConfig": {
|
|
12
|
+
"team_id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"title": "Invinite team ID",
|
|
15
|
+
"description": "Team billed for Data API usage. Copy it from the team-pinned MCP URL in Invinite Data API settings.",
|
|
16
|
+
"required": true
|
|
17
|
+
}
|
|
18
|
+
}
|
|
11
19
|
}
|
|
@@ -23,7 +23,7 @@ You are a financial data retrieval specialist. Your job is to fetch the requeste
|
|
|
23
23
|
- Always use `--json` on every data command
|
|
24
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
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
|
|
26
|
+
- If a command fails with an authentication error, report it clearly and tell the caller to run `invd login`; `INVINITE_DATA_API_KEY` and `invd config set-key` remain manual fallbacks
|
|
27
27
|
- If a company identifier is ambiguous, use `invd company search -q "<name>" --json` first to resolve it
|
|
28
28
|
- For comparing companies, prefer `invd financials snapshot -i AAPL,MSFT,GOOGL -p annual --json` over individual queries
|
|
29
29
|
- When fetching financial statements, default to `annual` period unless the request specifies otherwise
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Analyze a company's SEC filing for material changes, risks, management commentary, and evidence.
|
|
3
|
+
argument-hint: <ticker> [form type or research question]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Analyze SEC Filing
|
|
7
|
+
|
|
8
|
+
Analyze the filing requested in `$ARGUMENTS` using Invinite Data.
|
|
9
|
+
|
|
10
|
+
1. Resolve the company and identify the relevant filing and accession number.
|
|
11
|
+
2. Discover valid filing section IDs before requesting sections.
|
|
12
|
+
3. Retrieve only the sections needed for the question, normally risk factors, MD&A, business, and financial statements.
|
|
13
|
+
4. Separate direct filing evidence from your interpretation.
|
|
14
|
+
5. Report the form type, filing date, accession number, and section for every material finding.
|
|
15
|
+
6. Flag missing sections or unavailable periods instead of inferring their contents.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Compare the financial performance, valuation, growth, and risks of two or more companies.
|
|
3
|
+
argument-hint: <tickers or company names> [focus]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Compare Companies
|
|
7
|
+
|
|
8
|
+
Compare the companies in `$ARGUMENTS` using Invinite Data.
|
|
9
|
+
|
|
10
|
+
1. Resolve ambiguous company names with `company_search` or the equivalent `invd` command.
|
|
11
|
+
2. Fetch available metric definitions before requesting financial metrics.
|
|
12
|
+
3. Fetch company details, the latest annual standardized snapshot, profitability and valuation ratios, and five-year CAGR where available.
|
|
13
|
+
4. Run independent reads in parallel when the active Claude surface supports it.
|
|
14
|
+
5. Present a compact comparison table followed by the most material strengths, weaknesses, and data limitations.
|
|
15
|
+
6. Cite the reporting periods used; do not mix annual and quarterly values without labeling them.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review institutional ownership, position changes, concentration, and insider trading for a company.
|
|
3
|
+
argument-hint: <ticker> [period or focus]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review Ownership
|
|
7
|
+
|
|
8
|
+
Review ownership activity for `$ARGUMENTS` using Invinite Data.
|
|
9
|
+
|
|
10
|
+
1. Resolve the company identifier.
|
|
11
|
+
2. Fetch institutional holdings, institutional transactions, and insider trades for the requested period.
|
|
12
|
+
3. Identify the largest holders, notable new or exited positions, and meaningful insider acquisitions or dispositions.
|
|
13
|
+
4. Distinguish position value from share count and filing date from transaction date.
|
|
14
|
+
5. Present concise tables and call out reporting-lag limitations in institutional filings.
|
|
@@ -1,21 +1,51 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: invinite-data
|
|
3
|
-
description: Fetch financial data
|
|
2
|
+
name: invinite-financial-data
|
|
3
|
+
description: Fetch financial data through the Invinite Data API MCP connector or invd CLI. Use whenever the user wants company information, financial statements, SEC filings, institutional ownership, insider trades, IPO data, market holidays, financial metrics, or other stock/company data, including requests mentioning tickers, CIKs, balance sheets, income statements, cash flows, 10-K, 10-Q, ratios, CAGR, growth rates, dividends, stock splits, or institutional holdings.
|
|
4
4
|
allowed-tools: Bash(invd *)
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Invinite Data API
|
|
7
|
+
# Invinite Data API
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Use the connected Invinite Data API MCP tools when available. Fall back to the `invd` CLI when MCP is unavailable. Both transports access the same team-billed Data API.
|
|
10
|
+
|
|
11
|
+
## Transport selection
|
|
12
|
+
|
|
13
|
+
1. Prefer MCP tools when an Invinite Data connector is available. Call the direct domain tool matching the request; unlike the Web API MCP server, the Data API MCP server does not use meta-tools such as `call_endpoint`.
|
|
14
|
+
2. Use the CLI examples below when MCP is unavailable or when the user explicitly requests CLI usage. Always pass `--json` for data used in analysis.
|
|
15
|
+
3. Do not mix transports merely to repeat a successful request.
|
|
16
|
+
|
|
17
|
+
### MCP and CLI mapping
|
|
18
|
+
|
|
19
|
+
| Data need | MCP tool | CLI command family |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| Search/details/list | `company_search`, `company_details`, `available_companies` | `invd company ...` |
|
|
22
|
+
| Dividends/periods/splits | `company_dividends`, `company_fiscal_periods`, `company_splits` | `invd company ...` |
|
|
23
|
+
| Standardized statements/snapshots | `standardized_financial_statement`, `standardized_financial_snapshot` | `invd financials ...` |
|
|
24
|
+
| As-reported statements/snapshots | `as_reported_financial_statement`, `as_reported_financial_snapshot` | `invd financials ... --as-reported` |
|
|
25
|
+
| Ratios/growth/CAGR | `financial_ratios`, `financial_growth`, `financial_cagr` | `invd metrics ...` |
|
|
26
|
+
| Segment data | `segmented_financials` | `invd segments ...` |
|
|
27
|
+
| SEC filings/search/sections | `sec_filings`, `sec_filings_search`, `sec_filing_sections` | `invd filings ...` |
|
|
28
|
+
| Filing and metric discovery | `sec_available_form_types`, `list_available_section_ids`, `list_available_metrics` | `invd filings form-types`, `invd metadata ...` |
|
|
29
|
+
| Institutional ownership | `holdings_by_company`, `holdings_by_investor`, `institutional_investors`, `institutional_transactions` | `invd ownership ...` |
|
|
30
|
+
| Insider trades/IPOs/holidays | `insider_trades`, `ipos`, `market_holidays` | `invd insider-trades`, `invd ipos`, `invd market ...` |
|
|
31
|
+
|
|
32
|
+
The discovery rules below apply to both transports: call `list_available_metrics` before ratios, growth, CAGR, or financial-statement analysis, and call `list_available_section_ids` before requesting filing sections.
|
|
10
33
|
|
|
11
34
|
## Prerequisites
|
|
12
35
|
|
|
13
|
-
|
|
36
|
+
### MCP
|
|
37
|
+
|
|
38
|
+
Connect `https://data.invinite.com/t/<teamId>/mcp` through OAuth. The team in the URL controls data billing. Leave OAuth client ID and secret empty so the client uses Dynamic Client Registration and PKCE.
|
|
39
|
+
|
|
40
|
+
### CLI
|
|
41
|
+
|
|
42
|
+
Install the CLI with `npm install -g @invinite-org/invinite-data-cli`, then run `invd login` or `invd login --team <teamId>`. Authentication is resolved in this order:
|
|
14
43
|
1. `INVINITE_DATA_API_KEY` environment variable
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
44
|
+
2. `.env` file
|
|
45
|
+
3. OS keychain (via optional `keytar`)
|
|
46
|
+
4. Stored config
|
|
17
47
|
|
|
18
|
-
If
|
|
48
|
+
If an MCP call fails with an auth error, reconnect the connector and complete OAuth. If a CLI call fails with an auth error, run `invd login`; manual `invd config set-key` and `INVINITE_DATA_API_KEY` remain supported fallbacks.
|
|
19
49
|
|
|
20
50
|
## Global Options
|
|
21
51
|
|
package/dist/src/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ import { registerMarketCommands } from './commands/market.js';
|
|
|
14
14
|
import { registerMetadataCommands } from './commands/metadata.js';
|
|
15
15
|
import { registerWsCommands } from './commands/ws.js';
|
|
16
16
|
import { registerPluginCommands } from './commands/plugin.js';
|
|
17
|
+
import { registerLoginCommands } from './commands/login.js';
|
|
17
18
|
export function createProgram() {
|
|
18
19
|
const program = new Command();
|
|
19
20
|
program
|
|
@@ -42,6 +43,7 @@ export function createProgram() {
|
|
|
42
43
|
registerMetadataCommands(program);
|
|
43
44
|
registerWsCommands(program);
|
|
44
45
|
registerPluginCommands(program);
|
|
46
|
+
registerLoginCommands(program);
|
|
45
47
|
return program;
|
|
46
48
|
}
|
|
47
49
|
//# sourceMappingURL=cli.js.map
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +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;
|
|
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;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,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;IAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
type ExchangeData = {
|
|
3
|
+
key: string;
|
|
4
|
+
keyHint: string;
|
|
5
|
+
teamId: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
export type LoginDependencies = {
|
|
9
|
+
fetch: typeof fetch;
|
|
10
|
+
openBrowser: (url: string) => Promise<void>;
|
|
11
|
+
timeoutMs: number;
|
|
12
|
+
};
|
|
13
|
+
export declare function login(options?: {
|
|
14
|
+
team?: string;
|
|
15
|
+
}, dependencies?: LoginDependencies): Promise<ExchangeData>;
|
|
16
|
+
export declare function logout(dependencies?: Pick<LoginDependencies, 'fetch'>): Promise<void>;
|
|
17
|
+
export declare function registerLoginCommands(program: Command): void;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { hostname } from 'node:os';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { clearApiKey, resolveApiKey, setApiKey } from '../config/auth.js';
|
|
7
|
+
import { getBaseUrl } from '../config/config-manager.js';
|
|
8
|
+
const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
9
|
+
const KEY_LIFETIME_MS = 90 * 24 * 60 * 60 * 1000;
|
|
10
|
+
const MAX_BIND_ATTEMPTS = 3;
|
|
11
|
+
const defaultDependencies = {
|
|
12
|
+
fetch: globalThis.fetch,
|
|
13
|
+
openBrowser,
|
|
14
|
+
timeoutMs: CALLBACK_TIMEOUT_MS,
|
|
15
|
+
};
|
|
16
|
+
function errorMessage(error) {
|
|
17
|
+
return error instanceof Error ? error.message : String(error);
|
|
18
|
+
}
|
|
19
|
+
async function parseEnvelope(response) {
|
|
20
|
+
try {
|
|
21
|
+
return await response.json();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function browserCommand(url) {
|
|
28
|
+
if (process.platform === 'darwin')
|
|
29
|
+
return { command: 'open', args: [url] };
|
|
30
|
+
if (process.platform === 'win32')
|
|
31
|
+
return { command: 'cmd', args: ['/c', 'start', '', url] };
|
|
32
|
+
return { command: 'xdg-open', args: [url] };
|
|
33
|
+
}
|
|
34
|
+
async function openBrowser(url) {
|
|
35
|
+
const target = browserCommand(url);
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
const child = spawn(target.command, target.args, { detached: true, stdio: 'ignore' });
|
|
38
|
+
child.once('error', reject);
|
|
39
|
+
child.once('spawn', () => {
|
|
40
|
+
child.unref();
|
|
41
|
+
resolve();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function callbackHtml(title, message) {
|
|
46
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>${title}</title></head><body><main><h1>${title}</h1><p>${message}</p></main></body></html>`;
|
|
47
|
+
}
|
|
48
|
+
async function closeServer(server) {
|
|
49
|
+
if (!server.listening)
|
|
50
|
+
return;
|
|
51
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
52
|
+
}
|
|
53
|
+
async function listenOnRandomPort(server) {
|
|
54
|
+
for (let attempt = 0; attempt < MAX_BIND_ATTEMPTS; attempt += 1) {
|
|
55
|
+
const port = 49_152 + randomBytes(2).readUInt16BE(0) % (65_535 - 49_152 + 1);
|
|
56
|
+
try {
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const handleError = (error) => reject(error);
|
|
59
|
+
server.once('error', handleError);
|
|
60
|
+
server.listen(port, '127.0.0.1', () => {
|
|
61
|
+
server.off('error', handleError);
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return port;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error.code !== 'EADDRINUSE' || attempt === MAX_BIND_ATTEMPTS - 1)
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
throw new Error('Could not start the login callback server');
|
|
73
|
+
}
|
|
74
|
+
export async function login(options = {}, dependencies = defaultDependencies) {
|
|
75
|
+
const state = randomBytes(16).toString('hex');
|
|
76
|
+
let resolveCallback = () => undefined;
|
|
77
|
+
let rejectCallback = () => undefined;
|
|
78
|
+
const callback = new Promise((resolve, reject) => {
|
|
79
|
+
resolveCallback = resolve;
|
|
80
|
+
rejectCallback = reject;
|
|
81
|
+
});
|
|
82
|
+
let settled = false;
|
|
83
|
+
const settleError = (error) => {
|
|
84
|
+
if (settled)
|
|
85
|
+
return;
|
|
86
|
+
settled = true;
|
|
87
|
+
rejectCallback(error);
|
|
88
|
+
};
|
|
89
|
+
const settleSuccess = (data) => {
|
|
90
|
+
if (settled)
|
|
91
|
+
return;
|
|
92
|
+
settled = true;
|
|
93
|
+
resolveCallback(data);
|
|
94
|
+
};
|
|
95
|
+
const baseUrl = getBaseUrl().replace(/\/$/u, '');
|
|
96
|
+
const server = createServer(async (request, response) => {
|
|
97
|
+
const callbackUrl = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
98
|
+
if (request.method !== 'GET' || callbackUrl.pathname !== '/callback') {
|
|
99
|
+
response.writeHead(404).end();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (callbackUrl.searchParams.get('state') !== state) {
|
|
103
|
+
response.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
104
|
+
response.end(callbackHtml('Login failed', 'State verification failed. Return to the terminal and try again.'));
|
|
105
|
+
settleError(new Error('Login state verification failed'));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const code = callbackUrl.searchParams.get('code');
|
|
109
|
+
if (!code) {
|
|
110
|
+
response.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
111
|
+
response.end(callbackHtml('Login failed', 'The callback did not include an exchange code.'));
|
|
112
|
+
settleError(new Error('Login callback did not include an exchange code'));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const exchangeResponse = await dependencies.fetch(`${baseUrl}/auth/exchange`, {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify({ code }),
|
|
120
|
+
});
|
|
121
|
+
const envelope = await parseEnvelope(exchangeResponse);
|
|
122
|
+
if (!exchangeResponse.ok || !envelope?.ok) {
|
|
123
|
+
if (exchangeResponse.status === 401)
|
|
124
|
+
throw new Error('Login expired, run `invd login` again');
|
|
125
|
+
throw new Error(envelope && !envelope.ok ? envelope.error : `Login exchange failed (${exchangeResponse.status})`);
|
|
126
|
+
}
|
|
127
|
+
await setApiKey(envelope.data.key);
|
|
128
|
+
response.writeHead(200, {
|
|
129
|
+
'Cache-Control': 'no-store',
|
|
130
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
131
|
+
});
|
|
132
|
+
response.end(callbackHtml('Login complete', 'You can close this tab and return to the terminal.'));
|
|
133
|
+
settleSuccess(envelope.data);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
const exchangeError = error instanceof Error ? error : new Error(String(error));
|
|
137
|
+
response.writeHead(502, {
|
|
138
|
+
'Cache-Control': 'no-store',
|
|
139
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
140
|
+
});
|
|
141
|
+
response.end(callbackHtml('Login failed', 'The credential exchange failed. Return to the terminal and try again.'));
|
|
142
|
+
settleError(exchangeError);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const port = await listenOnRandomPort(server);
|
|
146
|
+
const loginUrl = new URL(`${baseUrl}/auth/login`);
|
|
147
|
+
loginUrl.searchParams.set('port', String(port));
|
|
148
|
+
loginUrl.searchParams.set('state', state);
|
|
149
|
+
loginUrl.searchParams.set('hostname', hostname().slice(0, 64));
|
|
150
|
+
if (options.team)
|
|
151
|
+
loginUrl.searchParams.set('team', options.team);
|
|
152
|
+
const handleInterrupt = () => settleError(new Error('Login cancelled'));
|
|
153
|
+
process.once('SIGINT', handleInterrupt);
|
|
154
|
+
const timeout = setTimeout(() => settleError(new Error('Login timed out. Run `invd login` again.')), dependencies.timeoutMs);
|
|
155
|
+
try {
|
|
156
|
+
const preflight = await dependencies.fetch(loginUrl, { redirect: 'manual' });
|
|
157
|
+
if (preflight.status === 503) {
|
|
158
|
+
throw new Error('OAuth login is not enabled on this deployment. Use `invd config set-key` instead.');
|
|
159
|
+
}
|
|
160
|
+
if (preflight.status < 300 || preflight.status >= 400) {
|
|
161
|
+
const envelope = await parseEnvelope(preflight);
|
|
162
|
+
throw new Error(envelope && !envelope.ok ? envelope.error : `Could not start login (${preflight.status})`);
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
await dependencies.openBrowser(loginUrl.toString());
|
|
166
|
+
console.log(chalk.dim('Opening your browser to complete login...'));
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
console.warn(chalk.yellow('Could not open a browser automatically. Open this URL:'));
|
|
170
|
+
console.log(loginUrl.toString());
|
|
171
|
+
}
|
|
172
|
+
const data = await callback;
|
|
173
|
+
const approximateExpiry = new Date(Date.now() + KEY_LIFETIME_MS).toLocaleDateString();
|
|
174
|
+
console.log(chalk.green('Logged in successfully.'));
|
|
175
|
+
console.log(` Team: ${data.teamId}`);
|
|
176
|
+
console.log(` Key hint: ${data.keyHint}`);
|
|
177
|
+
console.log(` Label: ${data.label}`);
|
|
178
|
+
console.log(` Expires: approximately ${approximateExpiry} (90 days)`);
|
|
179
|
+
console.log(chalk.dim('This sign-in is also visible in the web UI under Data API keys.'));
|
|
180
|
+
return data;
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
clearTimeout(timeout);
|
|
184
|
+
process.off('SIGINT', handleInterrupt);
|
|
185
|
+
await closeServer(server);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export async function logout(dependencies = defaultDependencies) {
|
|
189
|
+
let resolved;
|
|
190
|
+
try {
|
|
191
|
+
resolved = await resolveApiKey();
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
if (error instanceof Error && error.message.startsWith('No API key configured.')) {
|
|
195
|
+
console.log('Not logged in.');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
const baseUrl = getBaseUrl().replace(/\/$/u, '');
|
|
201
|
+
try {
|
|
202
|
+
const response = await dependencies.fetch(`${baseUrl}/auth/revoke`, {
|
|
203
|
+
method: 'POST',
|
|
204
|
+
headers: { Authorization: `Bearer ${resolved.key}` },
|
|
205
|
+
});
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
const envelope = await parseEnvelope(response);
|
|
208
|
+
console.warn(chalk.yellow(`Warning: remote revocation failed: ${envelope && !envelope.ok ? envelope.error : response.status}`));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.warn(chalk.yellow(`Warning: remote revocation failed: ${errorMessage(error)}`));
|
|
213
|
+
}
|
|
214
|
+
if (resolved.source === 'environment') {
|
|
215
|
+
console.log('The active key comes from INVINITE_DATA_API_KEY. Remove that environment variable to finish logging out.');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (resolved.source === 'dotenv') {
|
|
219
|
+
console.log('The active key comes from the current directory\'s .env file. Remove INVINITE_DATA_API_KEY from that file to finish logging out.');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
await clearApiKey();
|
|
223
|
+
console.log(chalk.green('Logged out locally.'));
|
|
224
|
+
}
|
|
225
|
+
export function registerLoginCommands(program) {
|
|
226
|
+
program
|
|
227
|
+
.command('login')
|
|
228
|
+
.description('Log in through your browser')
|
|
229
|
+
.option('--team <teamId>', 'Choose a team for the new API key')
|
|
230
|
+
.action(async (options) => {
|
|
231
|
+
try {
|
|
232
|
+
await login(options);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.error(chalk.red(errorMessage(error)));
|
|
236
|
+
process.exitCode = 1;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
program
|
|
240
|
+
.command('logout')
|
|
241
|
+
.description('Revoke the current login and clear local credentials')
|
|
242
|
+
.action(async () => {
|
|
243
|
+
try {
|
|
244
|
+
await logout();
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
console.error(chalk.red(errorMessage(error)));
|
|
248
|
+
process.exitCode = 1;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
export type ApiKeySource = 'environment' | 'dotenv' | 'keychain' | 'config';
|
|
2
|
+
export interface ResolvedApiKey {
|
|
3
|
+
key: string;
|
|
4
|
+
source: ApiKeySource;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveApiKey(): Promise<ResolvedApiKey>;
|
|
1
7
|
export declare function getApiKey(): Promise<string>;
|
|
2
8
|
export declare function setApiKey(key: string): Promise<void>;
|
|
9
|
+
export declare function clearApiKey(): Promise<void>;
|
package/dist/src/config/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { getStoredApiKey, setStoredApiKey } from './config-manager.js';
|
|
3
|
+
import { deleteStoredApiKey, getStoredApiKey, setStoredApiKey } from './config-manager.js';
|
|
4
4
|
async function tryKeytar() {
|
|
5
5
|
try {
|
|
6
6
|
// Dynamic import - keytar is optional
|
|
@@ -36,27 +36,31 @@ function readDotEnvKey() {
|
|
|
36
36
|
}
|
|
37
37
|
const SERVICE = 'invinite-data-cli';
|
|
38
38
|
const ACCOUNT = 'api-key';
|
|
39
|
-
export async function
|
|
39
|
+
export async function resolveApiKey() {
|
|
40
40
|
// 1. Environment variable (highest priority)
|
|
41
41
|
const envKey = process.env.INVINITE_DATA_API_KEY;
|
|
42
42
|
if (envKey)
|
|
43
|
-
return envKey;
|
|
43
|
+
return { key: envKey, source: 'environment' };
|
|
44
44
|
// 2. .env file in current working directory
|
|
45
45
|
const dotEnvKey = readDotEnvKey();
|
|
46
46
|
if (dotEnvKey)
|
|
47
|
-
return dotEnvKey;
|
|
47
|
+
return { key: dotEnvKey, source: 'dotenv' };
|
|
48
48
|
// 3. OS keychain via keytar
|
|
49
49
|
const keytar = await tryKeytar();
|
|
50
50
|
if (keytar) {
|
|
51
51
|
const keychainKey = await keytar.getPassword(SERVICE, ACCOUNT);
|
|
52
52
|
if (keychainKey)
|
|
53
|
-
return keychainKey;
|
|
53
|
+
return { key: keychainKey, source: 'keychain' };
|
|
54
54
|
}
|
|
55
55
|
// 4. Conf fallback
|
|
56
56
|
const storedKey = getStoredApiKey();
|
|
57
57
|
if (storedKey)
|
|
58
|
-
return storedKey;
|
|
59
|
-
throw new Error('No API key configured.
|
|
58
|
+
return { key: storedKey, source: 'config' };
|
|
59
|
+
throw new Error('No API key configured. Run: invd login');
|
|
60
|
+
}
|
|
61
|
+
export async function getApiKey() {
|
|
62
|
+
const resolved = await resolveApiKey();
|
|
63
|
+
return resolved.key;
|
|
60
64
|
}
|
|
61
65
|
export async function setApiKey(key) {
|
|
62
66
|
const keytar = await tryKeytar();
|
|
@@ -67,4 +71,15 @@ export async function setApiKey(key) {
|
|
|
67
71
|
setStoredApiKey(key);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
74
|
+
export async function clearApiKey() {
|
|
75
|
+
const keytar = await tryKeytar();
|
|
76
|
+
try {
|
|
77
|
+
if (keytar) {
|
|
78
|
+
await keytar.deletePassword(SERVICE, ACCOUNT);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
deleteStoredApiKey();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
70
85
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/config/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/config/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,6 @@ export declare function getBaseUrl(): string;
|
|
|
2
2
|
export declare function setBaseUrl(url: string): void;
|
|
3
3
|
export declare function getStoredApiKey(): string | undefined;
|
|
4
4
|
export declare function setStoredApiKey(key: string): void;
|
|
5
|
+
export declare function deleteStoredApiKey(): void;
|
|
5
6
|
export declare function resetConfig(): void;
|
|
6
7
|
export declare function showConfig(): Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/config/config-manager.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAe;IACpC,WAAW,EAAE,mBAAmB;IAChC,MAAM,EAAE;QACN,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,2BAA2B;SACrC;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;SACZ;KACF;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU;IACxB,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,GAAG,IAAI,SAAS,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,OAAO,EAAE,UAAU,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,eAAe,EAAE;KAC/B,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../../src/config/config-manager.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAe;IACpC,WAAW,EAAE,mBAAmB;IAChC,MAAM,EAAE;QACN,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,2BAA2B;SACrC;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;SACZ;KACF;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU;IACxB,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,GAAG,IAAI,SAAS,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO;QACL,OAAO,EAAE,UAAU,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,eAAe,EAAE;KAC/B,CAAC;AACJ,CAAC"}
|