@invinite-org/invinite-data-cli 0.13.1 → 1.0.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.
- package/README.md +35 -3
- package/claude-plugin/agents/invinite-data.md +1 -1
- package/claude-plugin/skills/invinite-data-cli/SKILL.md +131 -27
- package/dist/src/cli.js +3 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/client/api-client.d.ts +8 -0
- package/dist/src/client/api-client.js +16 -1
- package/dist/src/client/api-client.js.map +1 -1
- package/dist/src/client/download.d.ts +33 -0
- package/dist/src/client/download.js +101 -1
- package/dist/src/client/download.js.map +1 -1
- package/dist/src/commands/sec.d.ts +47 -0
- package/dist/src/commands/sec.js +191 -0
- package/dist/src/commands/sec.js.map +1 -0
- package/dist/src/formatters/table-formatter.d.ts +1 -0
- package/dist/src/formatters/table-formatter.js +12 -2
- package/dist/src/formatters/table-formatter.js.map +1 -1
- package/dist/src/generated/cli-manifest.json +1685 -217
- package/dist/src/hand-written-commands.d.ts +9 -0
- package/dist/src/hand-written-commands.js +3 -0
- package/dist/src/hand-written-commands.js.map +1 -1
- package/dist/src/shared/errors.d.ts +24 -1
- package/dist/src/shared/errors.js +41 -3
- package/dist/src/shared/errors.js.map +1 -1
- package/dist/src/shared/json-mode.d.ts +2 -0
- package/dist/src/shared/json-mode.js +12 -0
- package/dist/src/shared/json-mode.js.map +1 -0
- package/dist/src/shared/readiness.d.ts +4 -0
- package/dist/src/shared/readiness.js +35 -0
- package/dist/src/shared/readiness.js.map +1 -0
- package/dist/src/shared/spinner.js +2 -0
- package/dist/src/shared/spinner.js.map +1 -1
- package/dist/src/spec-commands.js +5 -1
- package/dist/src/spec-commands.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -204,7 +204,7 @@ route's `x-cli` (`invd <group> <action>`), its flags the operation's parameters
|
|
|
204
204
|
text the spec's summary and parameter descriptions. List them with `invd --help` and `invd <group> --help`; the
|
|
205
205
|
[plugin skill](claude-plugin/skills/invinite-data-cli/SKILL.md#commands-reference) carries one generated example per
|
|
206
206
|
command. A handful of commands are hand-written because they do more than one call — `login`, `logout`, `config`,
|
|
207
|
-
`plugin`, `ws
|
|
207
|
+
`plugin`, `ws`, the earnings downloads / text renders below and the `sec` downloads (`src/hand-written-commands.ts`).
|
|
208
208
|
|
|
209
209
|
| Group | What it covers |
|
|
210
210
|
|-------|----------------|
|
|
@@ -212,7 +212,7 @@ command. A handful of commands are hand-written because they do more than one ca
|
|
|
212
212
|
| `financials` | Standardized and as-reported statements and snapshots — one command per variant: `income-statement`, `income-statement-detailed`, `income-statement-presentation`, `as-reported-income-statement…`; the same for `balance-sheet`, `cash-flow`, `snapshot` |
|
|
213
213
|
| `metrics` | Ratios, growth, CAGR |
|
|
214
214
|
| `segments` | `list`, `list-detailed` |
|
|
215
|
-
| `
|
|
215
|
+
| `sec` | Invinite's SEC document store: `filers`, `filer`, `lifecycle`, `issuers`, `filings` (cursor-paged, `form_facet`), `filing` (its document manifest), `document` / `version` (immutable cited blocks, pages, footnotes), `sections`, `figure`, `fact-places`, `search` (`--mode lexical\|literal`, 100 credits), 13F `holders` / `portfolio` / `holding-deltas` / `form-filers`, `financials-catalog` / `statement` / `financial-fact`, `metric-export` / `export`, `datasets`; downloads `save` (originals), `save-figure`, `export-file` |
|
|
216
216
|
| `earnings` | Calendar, events, live calls, transcripts, Q&A, participants, analysts, guidance and KPI extractions, diff, metrics, prosody, price moves during the call, media, documents, search, company IR documents |
|
|
217
217
|
| `news` | News of US companies from SEC filings and their own newsrooms: `list` (cursor-paged), `get` (full text + attribution), `text` (citable blocks), `developments`, `search` (passages; off until the API enables it), `asset-download` |
|
|
218
218
|
| `ownership` | 13F holdings by company / investor, institutions, transactions |
|
|
@@ -229,7 +229,10 @@ invd financials as-reported-cash-flow -i GOOGL -p annual --json
|
|
|
229
229
|
invd financials snapshot -i AAPL,MSFT,GOOGL -p annual --json
|
|
230
230
|
invd metrics ratios -i AAPL -p annual --category profitability --json
|
|
231
231
|
invd segments list-detailed -i AAPL -p annual --json
|
|
232
|
-
invd filings
|
|
232
|
+
invd sec filings -i AAPL -f 10-K -l 5 --json
|
|
233
|
+
invd sec filing --accession 0000320193-26-000024 --json
|
|
234
|
+
invd sec document --accession 0000320193-26-000024 --filename aapl-20261102.htm -l 20 --json
|
|
235
|
+
invd sec search -q "supply chain concentration" -m lexical -c 320193 --json
|
|
233
236
|
invd ownership holdings-by-company -i AAPL --min-value 1000000 --json
|
|
234
237
|
invd insider-trades list -i TSLA --acquired-disposed D --limit 20 --json
|
|
235
238
|
invd earnings events -i AAPL -s desc -l 4 --json
|
|
@@ -341,6 +344,35 @@ invd ws listen --news --tickers NVDA
|
|
|
341
344
|
|
|
342
345
|
---
|
|
343
346
|
|
|
347
|
+
### sec
|
|
348
|
+
|
|
349
|
+
Invinite's SEC document store (`/v1/sec/*`, STANDARD; 1 credit a call, `sec search` 100). Every answer carries
|
|
350
|
+
`readiness` (`ready`, `partial`, `pending` = 202 not billed, retry later; `excluded` 403, `unknown` 404, `failed` 424,
|
|
351
|
+
`not_ready` 503 = the capability is not switched on yet) and the human output prints a yellow stderr line whenever the
|
|
352
|
+
answer is not ready or a search's `coverage.completeness` is not `complete` — zero rows there is **not** "nothing
|
|
353
|
+
exists". `--json` keeps every source field (version, block, page, `next_cursor`); an error prints its code
|
|
354
|
+
(`Error 503: not_ready (search_provider_not_registered)`) and, with `--json`, the whole structured body as one JSON
|
|
355
|
+
line on stderr. Pages use an opaque cursor: `--all` follows `next_url`, by hand pass `next_cursor` as `--cursor`
|
|
356
|
+
with the same filters (a `409 restart_required` = start again).
|
|
357
|
+
|
|
358
|
+
A citation is the immutable `version_id` + `block_id` (plus the printed page label when the document states one,
|
|
359
|
+
else the page ordinal) — never a URL. Search is `--mode lexical` (keywords, ranked) or `--mode literal` (exact text,
|
|
360
|
+
`--case-sensitive false` folds case); there is no semantic mode and no prose answer.
|
|
361
|
+
|
|
362
|
+
| Download | What it does |
|
|
363
|
+
|---|---|
|
|
364
|
+
| `sec save --accession <a> [--filename <f>] -o <dir>` | Saves a filing's originals from their permanent public copies, no API key on the download, size + SHA-256 from the manifest verified. A document without a public copy (or quarantined / too large) is listed with its reason and the command exits **3**; nothing is skipped silently |
|
|
365
|
+
| `sec save-figure --version-id <v> --block-id <b> -o <path>` | Saves a figure's image from its permanent public URL |
|
|
366
|
+
| `sec export-file --export-id <id> -o <path> [--sha256 <hex>]` | Streams a metric export's `.csv.gz` through the key-authorized route, verified against `X-Content-SHA256` (and `--sha256`); with `--sha256`, an identical existing file is complete without a request |
|
|
367
|
+
|
|
368
|
+
Downloads write `<file>.part` and rename it only after every check: exit **4** = partial download, **5** = size / hash /
|
|
369
|
+
media-type mismatch — nothing is saved either way; an existing file needs `--force`. No command ever fetches sec.gov.
|
|
370
|
+
|
|
371
|
+
The legacy `filings list|search|sections|form-types` (`/v1/sec-filings/*`) were removed in 1.0.0. Use `sec filings`
|
|
372
|
+
for `filings list` (its `form_facet` replaces `filings form-types`), `sec document` (pins the version) + `sec sections`
|
|
373
|
+
+ `sec version --blocks` for `filings sections`, and `sec search -m lexical|literal` for `filings search` (cited
|
|
374
|
+
passages, no prose answer, 100 credits).
|
|
375
|
+
|
|
344
376
|
### webhooks
|
|
345
377
|
|
|
346
378
|
Earnings-call webhook subscriptions (PRO): signed, retried `POST`s of the call lifecycle to your HTTPS endpoint. Events: `earnings_call.scheduled`, `.rescheduled`, `.started`, `.ended`, `.transcript_provisional`, `.transcript_ready`, `.transcript_corrected`, `.assets_ready`, `.keyword_hit` (one delivery per mention of one of the subscription's keywords on a live call, with the speaker, `start_ms` and the sentence), `.guidance_flash` (a guidance number spoken live, before the final transcript), `news.published` (STANDARD and above: one delivery per new news item, `data.item` = a `news list` row, filtered by the CIKs it mentions), and `ping`. Deliveries carry `X-Invinite-Signature: t=…,v1=…` (HMAC-SHA256 of `<t>.<raw body>` with the secret) and are retried after 1 min, 5 min, 30 min, 2 h, 6 h, 12 h and 24 h.
|
|
@@ -40,7 +40,7 @@ Common multi-step patterns:
|
|
|
40
40
|
- **Company research**: metadata metrics (first) + company details + financials snapshot + metrics ratios
|
|
41
41
|
- **Metrics analysis**: metadata metrics (first) → then ratios/CAGR/growth queries
|
|
42
42
|
- **Ownership analysis**: holdings-by-company + ownership transactions
|
|
43
|
-
- **Filing deep-dive**:
|
|
43
|
+
- **Filing deep-dive**: sec filings (first, for the accession) → sec filing (document manifest) → sec document (pins the `version_id`) → sec sections → sec version `--blocks` for the section's text; sec search `-m lexical|literal` for cited passages on a topic
|
|
44
44
|
- **Comparative analysis**: metadata metrics (first) + financials snapshot with multiple tickers + metrics ratios for each
|
|
45
45
|
- **Earnings call review**: earnings events (first, for the `event_id`) → then in parallel press-release + extractions `--kind guidance` + extractions `--kind kpi` + qa + diff (+ optionally price-attribution: minute price moves next to what was said — temporal coincidence, not cause)
|
|
46
46
|
- **Guidance tracking**: earnings guidance-history `--metric <metric>` across calls + extractions of the latest call
|
|
@@ -24,8 +24,9 @@ Use the connected Invinite Data API MCP tools when available. Fall back to the `
|
|
|
24
24
|
| As-reported statements/snapshots | `as_reported_financial_statement`, `as_reported_financial_snapshot` | `invd financials as-reported-<statement>…`, `invd financials as-reported-snapshot…` |
|
|
25
25
|
| Ratios/growth/CAGR | `financial_ratios`, `financial_growth`, `financial_cagr` | `invd metrics ratios\|growth\|cagr` |
|
|
26
26
|
| Segment data | `segmented_financials` | `invd segments list\|list-detailed` |
|
|
27
|
-
| SEC filings/search/sections (a CIK also finds a not-yet-listed company
|
|
28
|
-
|
|
|
27
|
+
| SEC filings/search/sections (a CIK also finds a not-yet-listed company) | `sec_filer_filings`, `sec_document_search`, `sec_document_sections` | `invd sec filings\|search\|sections` |
|
|
28
|
+
| SEC document store: filers / issuer lifecycle, filings + document manifests, immutable cited document versions (blocks, pages, footnotes, figures, sections), lexical / literal search, 13F research, statement provenance, metric exports (typed `readiness`) | `sec_filers`, `sec_filer`, `sec_filer_lifecycle`, `sec_filer_filings`, `sec_filing`, `sec_document`, `sec_document_version`, `sec_document_sections`, `sec_document_search`, `sec_holders`, `sec_manager_portfolio`, `sec_metric_export`, … | `invd sec …` (`sec save`, `sec save-figure`, `sec export-file` download, CLI-only) |
|
|
29
|
+
| Filing and metric discovery | `sec_filer_filings` (`form_facet`), `list_available_section_ids`, `list_available_metrics` | `invd sec filings` (`form_facet`), `invd metadata section-ids\|metrics` |
|
|
29
30
|
| Institutional ownership | `holdings_by_company`, `holdings_by_investor`, `institutional_investors`, `institutional_transactions` | `invd ownership …` |
|
|
30
31
|
| Insider trades/IPOs/holidays | `insider_trades`, `ipos`, `market_holidays` | `invd insider-trades list`, `invd ipos list`, `invd market holidays` |
|
|
31
32
|
| Upcoming IPOs from SEC registrations (S-1 / F-1, by CIK, weeks before the IPO calendar; stage, proposed ticker, price range, final price) | `ipo_registrations` | `invd ipos registrations` |
|
|
@@ -117,7 +118,8 @@ All share the same `metric_id` identifiers from `metadata metrics`.
|
|
|
117
118
|
|
|
118
119
|
### Filings, ownership, insider trades
|
|
119
120
|
|
|
120
|
-
-
|
|
121
|
+
- `invd sec …` reads Invinite's SEC document store: `sec filings -i <ticker|CIK>` (cursor pages, `form_facet`), `sec filing --accession` (document manifest: role, MIME, true size, readiness), `sec document --accession --filename` (pins the immutable version; blocks with `citation {version_id, block_id, page, printed}`), `sec search -q … --mode lexical|literal` (100 credits). Cite `version_id` + `block_id` and the printed page label only when present (else the page ordinal). `readiness.status` `pending` / `partial` / `not_ready` and a search `coverage.completeness` other than `complete` mean the answer is incomplete — never report zero rows there as "nothing found".
|
|
122
|
+
- Filing sections: `sec document` (pins the `version_id`) → `sec sections --version-id` → `sec version --version-id … --blocks <range>` for the text. `sec search` returns cited passages (no prose answer) at 100 credits a call. The legacy `filings list|search|sections|form-types` were removed in 1.0.0.
|
|
121
123
|
- Ownership transaction types (`--type`): `new_buy`, `added`, `reduced`, `sold_out`. `holdings-by-investor` needs the investor's `--cik`.
|
|
122
124
|
- Insider trades `--acquired-disposed`: `A` (acquisition) or `D` (disposition).
|
|
123
125
|
|
|
@@ -213,7 +215,7 @@ Earnings calls: calendar, transcripts, Q&A, extractions, media, search and webho
|
|
|
213
215
|
# Analysts of a company (optional: --limit, --offset, --all)
|
|
214
216
|
invd earnings analysts -i MSFT --json
|
|
215
217
|
|
|
216
|
-
# Earnings call calendar (optional: --from, --to, --status, --session, --exchange, --event-type, --sort, --limit, --offset, --all)
|
|
218
|
+
# Earnings call calendar (optional: --from, --to, --status, --session, --exchange, --event-type, --sort, --limit, --offset, --date-kind, --calendar-status, --all)
|
|
217
219
|
invd earnings calendar --json
|
|
218
220
|
|
|
219
221
|
# Call-over-call diff (optional: --event-id, --identifier, --year, --quarter, --date, --event-type, --vs)
|
|
@@ -331,24 +333,6 @@ invd earnings document --document-id <document_id> --output annual-report.pdf
|
|
|
331
333
|
```
|
|
332
334
|
<!-- /invd:hand:earnings document -->
|
|
333
335
|
|
|
334
|
-
### filings
|
|
335
|
-
|
|
336
|
-
SEC filings, their parsed sections and natural-language filing search
|
|
337
|
-
|
|
338
|
-
```bash
|
|
339
|
-
# Available SEC form types (optional: --identifier)
|
|
340
|
-
invd filings form-types --json
|
|
341
|
-
|
|
342
|
-
# SEC filings (optional: --form-type, --sort, --limit, --offset, --all)
|
|
343
|
-
invd filings list -i AAPL --json
|
|
344
|
-
|
|
345
|
-
# Search SEC filings (optional: --identifier, --accession-number)
|
|
346
|
-
invd filings search -r "What are Apple's main risk factors?" -i AAPL --json
|
|
347
|
-
|
|
348
|
-
# SEC filing sections (optional: --section-id, --accession-number, --fiscal-year, --fiscal-quarter)
|
|
349
|
-
invd filings sections -i AAPL --form-type 10-K --fiscal-year 2025 --json
|
|
350
|
-
```
|
|
351
|
-
|
|
352
336
|
### financials
|
|
353
337
|
|
|
354
338
|
Financial statements (standardized & as-reported)
|
|
@@ -453,7 +437,7 @@ Initial public offerings
|
|
|
453
437
|
# List IPOs (optional: --start-date, --end-date, --sort, --limit, --offset, --all)
|
|
454
438
|
invd ipos list --json
|
|
455
439
|
|
|
456
|
-
# List IPO registrations (SEC) (optional: --start-date, --end-date, --stage, --is-spac, --sort, --limit, --offset, --all)
|
|
440
|
+
# List IPO registrations (SEC) (optional: --start-date, --end-date, --stage, --is-spac, --pending, --sort, --limit, --offset, --all)
|
|
457
441
|
invd ipos registrations --json
|
|
458
442
|
```
|
|
459
443
|
|
|
@@ -565,6 +549,122 @@ invd plugin uninstall --claude --global
|
|
|
565
549
|
```
|
|
566
550
|
<!-- /invd:hand:plugin -->
|
|
567
551
|
|
|
552
|
+
### sec
|
|
553
|
+
|
|
554
|
+
Invinite's SEC document store: filers and issuer lifecycle, filings with their documents, immutable cited document versions (blocks, pages, figures, sections, XBRL fact places), lexical / literal search, 13F holdings research, standardized-statement provenance and metric exports
|
|
555
|
+
|
|
556
|
+
```bash
|
|
557
|
+
# SEC dataset releases
|
|
558
|
+
invd sec datasets --json
|
|
559
|
+
|
|
560
|
+
# SEC document (current version) (optional: --blocks, --pages, --printed, --printed-occurrence, --neighbors, --footnotes, --limit)
|
|
561
|
+
invd sec document --accession 0000320193-26-000026 --filename aapl-20260926.htm --json
|
|
562
|
+
|
|
563
|
+
# Metric export manifest
|
|
564
|
+
invd sec export --export-id 6a7350b9-df18-517b-b553-96601b1e0508 --json
|
|
565
|
+
|
|
566
|
+
# XBRL fact places in a document version (optional: --fact-id, --status, --cursor, --limit, --all)
|
|
567
|
+
invd sec fact-places --version-id 8be0b759-1a9d-5f89-8308-bd86185f5e1f --json
|
|
568
|
+
|
|
569
|
+
# SEC document figure
|
|
570
|
+
invd sec figure --version-id 8be0b759-1a9d-5f89-8308-bd86185f5e1f --block-id b00107 --json
|
|
571
|
+
|
|
572
|
+
# SEC filer
|
|
573
|
+
invd sec filer --cik 320193 --json
|
|
574
|
+
|
|
575
|
+
# SEC filer document coverage (optional: --since)
|
|
576
|
+
invd sec filer-coverage --cik 320193 --json
|
|
577
|
+
|
|
578
|
+
# Find SEC filers (optional: --name, --ticker, --form, --limit)
|
|
579
|
+
invd sec filers --json
|
|
580
|
+
|
|
581
|
+
# SEC filing and its documents
|
|
582
|
+
invd sec filing -a 0000320193-26-000026 --json
|
|
583
|
+
|
|
584
|
+
# SEC dataset facts of a filing (optional: --tag)
|
|
585
|
+
invd sec filing-facts --accession 0000320193-26-000026 --json
|
|
586
|
+
|
|
587
|
+
# Holdings of a 13F filing (optional: --after, --limit, --all)
|
|
588
|
+
invd sec filing-holdings --accession 0000320193-26-000026 --json
|
|
589
|
+
|
|
590
|
+
# SEC dataset text notes of a filing (optional: --tag)
|
|
591
|
+
invd sec filing-notes --accession 0000320193-26-000026 --json
|
|
592
|
+
|
|
593
|
+
# SEC filings of a filer (optional: --form, --filed-from, --filed-to, --order, --cursor, --limit, --all)
|
|
594
|
+
invd sec filings -i AAPL --json
|
|
595
|
+
|
|
596
|
+
# Explain a standardized fact (optional: --max-depth, --max-members, --places)
|
|
597
|
+
invd sec financial-fact --id "320193|is_total_revenue|annual|2026|4" --json
|
|
598
|
+
|
|
599
|
+
# Standardization rule catalog (optional: --statement, --metric-id)
|
|
600
|
+
invd sec financials-catalog --json
|
|
601
|
+
|
|
602
|
+
# Filers of an SEC form (optional: --exact, --name, --cik, --cursor, --limit, --all)
|
|
603
|
+
invd sec form-filers -f 13F-HR --json
|
|
604
|
+
|
|
605
|
+
# Institutional holders of a security (13F) (optional: --cusip, --symbol, --issuer-cik, --instruments, --pinned-at, --cursor, --limit, --all)
|
|
606
|
+
invd sec holders --period-end 2026-06-30 --json
|
|
607
|
+
|
|
608
|
+
# Position changes in a security (13F) (optional: --prior-period-end, --cusip, --symbol, --issuer-cik, --instruments, --pinned-at, --cursor, --limit, --all)
|
|
609
|
+
invd sec holding-deltas --period-end 2026-06-30 --json
|
|
610
|
+
|
|
611
|
+
# List SEC issuers (optional: --query, --phase, --form, --public-seen-from, --public-seen-to, --cursor, --limit, --all)
|
|
612
|
+
invd sec issuers --json
|
|
613
|
+
|
|
614
|
+
# SEC issuer lifecycle (optional: --traverse, --max-hops)
|
|
615
|
+
invd sec lifecycle --cik 320193 --json
|
|
616
|
+
|
|
617
|
+
# Request an annual metric export (optional: --period-type, --mode, --generation)
|
|
618
|
+
invd sec metric-export -m is_total_revenue -y 2025 --json
|
|
619
|
+
|
|
620
|
+
# Portfolio of a 13F manager (optional: --instruments, --pinned-at, --cursor, --limit, --all)
|
|
621
|
+
invd sec portfolio --period-end 2026-06-30 --cik 1067983 --json
|
|
622
|
+
|
|
623
|
+
# SEC review chain of a filing (optional: --max-depth, --max-nodes)
|
|
624
|
+
invd sec review-chain --accession 0000320193-26-000026 --json
|
|
625
|
+
|
|
626
|
+
# SEC review relations of a filing (optional: --direction, --kind, --history, --cursor, --limit, --all)
|
|
627
|
+
invd sec review-relations --accession 0000320193-26-000026 --json
|
|
628
|
+
|
|
629
|
+
# Search SEC documents (optional: --mode, --case-sensitive, --cik, --entity-id, --successors, --accession, --version-id, --form, --filename, --item, --exhibit-type, --filed-from, --filed-to, --cursor, --limit, --all)
|
|
630
|
+
invd sec search -q "supply chain concentration" --json
|
|
631
|
+
|
|
632
|
+
# Sections of an SEC document version (optional: --outline)
|
|
633
|
+
invd sec sections --version-id 8be0b759-1a9d-5f89-8308-bd86185f5e1f --json
|
|
634
|
+
|
|
635
|
+
# Standardized statement with provenance (optional: --period-type, --fiscal-year-from, --fiscal-year-to, --metric-id, --other-evidence, --limit)
|
|
636
|
+
invd sec statement --cik 320193 --statement income_statement --json
|
|
637
|
+
|
|
638
|
+
# SEC document version (optional: --blocks, --pages, --printed, --printed-occurrence, --neighbors, --footnotes, --limit)
|
|
639
|
+
invd sec version --version-id 8be0b759-1a9d-5f89-8308-bd86185f5e1f --json
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
<!-- invd:hand:sec save -->
|
|
643
|
+
```bash
|
|
644
|
+
# Save a filing's originals from their permanent public copies (size + SHA-256 verified); every document it
|
|
645
|
+
# cannot save is listed with its reason (no public copy yet, quarantined, too large) and the exit code is 3
|
|
646
|
+
invd sec save --accession 0000320193-26-000024 -o filings/aapl-8k/
|
|
647
|
+
invd sec save --accession 0000320193-26-000024 --filename aapl-20261102.htm --json
|
|
648
|
+
```
|
|
649
|
+
<!-- /invd:hand:sec save -->
|
|
650
|
+
|
|
651
|
+
<!-- invd:hand:sec save-figure -->
|
|
652
|
+
```bash
|
|
653
|
+
# Save a cited figure's image from its permanent public URL; the citation is version_id#block_id, never a URL
|
|
654
|
+
invd sec save-figure --version-id 402affed-8245-5fe1-814d-d025f60db4ac --block-id b00012 -o figures/
|
|
655
|
+
```
|
|
656
|
+
<!-- /invd:hand:sec save-figure -->
|
|
657
|
+
|
|
658
|
+
<!-- invd:hand:sec export-file -->
|
|
659
|
+
```bash
|
|
660
|
+
# Download a metric export (.csv.gz) through the key-authorized route, verified against its SHA-256;
|
|
661
|
+
# --sha256 (from invd sec export) also accepts an identical existing file without a request.
|
|
662
|
+
# Exit 4 = partial download, 5 = size / hash / type mismatch: nothing is saved either way
|
|
663
|
+
invd sec export-file --export-id 6a7350b9-df18-517b-b553-96601b1e0508 -o exports/
|
|
664
|
+
invd sec export-file --export-id 6a7350b9-df18-517b-b553-96601b1e0508 -o exports/revenue-2025.csv.gz --sha256 <sha256>
|
|
665
|
+
```
|
|
666
|
+
<!-- /invd:hand:sec export-file -->
|
|
667
|
+
|
|
568
668
|
### segments
|
|
569
669
|
|
|
570
670
|
Financial facts broken down by business and geographic segment
|
|
@@ -679,8 +779,9 @@ invd ownership holdings-by-company -i AAPL --min-value 10000000 --json
|
|
|
679
779
|
```
|
|
680
780
|
|
|
681
781
|
### Searching SEC filings by topic
|
|
782
|
+
Cited passages (`version_id` + `block_id`), no prose answer; 100 credits:
|
|
682
783
|
```bash
|
|
683
|
-
invd
|
|
784
|
+
invd sec search -q "artificial intelligence strategy" -m lexical -c 789019 --json
|
|
684
785
|
```
|
|
685
786
|
|
|
686
787
|
### Reading an earnings call
|
|
@@ -707,10 +808,13 @@ invd news developments --publisher 1045810 --topic product_launch --json
|
|
|
707
808
|
Answer with the publisher, the date and the link of each item (`attribution`), and keep "announced" / "planned" claims as such.
|
|
708
809
|
|
|
709
810
|
### Reading specific filing sections
|
|
710
|
-
|
|
811
|
+
Find the filing, pin the document version, list its sections, then read a section's blocks:
|
|
711
812
|
```bash
|
|
712
|
-
invd
|
|
713
|
-
invd
|
|
813
|
+
invd sec filings -i AAPL -f 10-K -l 1 --json # pick the accession
|
|
814
|
+
invd sec filing --accession <accession> --json # document manifest: the primary filename
|
|
815
|
+
invd sec document --accession <accession> --filename <filename> -l 1 --json # version.version_id
|
|
816
|
+
invd sec sections --version-id <version_id> --json # each section's blocks selector
|
|
817
|
+
invd sec version --version-id <version_id> --blocks <blocks> --json
|
|
714
818
|
```
|
|
715
819
|
|
|
716
820
|
## Tips
|
package/dist/src/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import { registerEarningsCommands } from './commands/earnings.js';
|
|
|
7
7
|
import { registerLoginCommands } from './commands/login.js';
|
|
8
8
|
import { registerNewsCommands } from './commands/news.js';
|
|
9
9
|
import { registerPluginCommands } from './commands/plugin.js';
|
|
10
|
+
import { registerSecCommands } from './commands/sec.js';
|
|
10
11
|
import { registerWsCommands } from './commands/ws.js';
|
|
11
12
|
import { registerSpecCommands } from './spec-commands.js';
|
|
12
13
|
import { parseManifest } from './spec-manifest.js';
|
|
@@ -60,13 +61,14 @@ export function createProgram() {
|
|
|
60
61
|
console.error(formatCreditUsage(usage));
|
|
61
62
|
});
|
|
62
63
|
// The hand-written roster (`src/hand-written-commands.ts`) first, then every manifest operation; a generated
|
|
63
|
-
// `earnings` action attaches to the group
|
|
64
|
+
// `earnings` / `news` / `sec` action attaches to the group its hand-written commands created.
|
|
64
65
|
registerLoginCommands(program);
|
|
65
66
|
registerConfigCommands(program);
|
|
66
67
|
registerPluginCommands(program);
|
|
67
68
|
registerWsCommands(program);
|
|
68
69
|
registerEarningsCommands(program);
|
|
69
70
|
registerNewsCommands(program);
|
|
71
|
+
registerSecCommands(program);
|
|
70
72
|
registerSpecCommands(program, loadManifest());
|
|
71
73
|
return program;
|
|
72
74
|
}
|
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,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAiB,MAAM,oBAAoB,CAAC;AAElE,MAAM,YAAY,GAAG,iCAAiC,CAAC;AAEvD,uGAAuG;AACvG,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,KAAK,MAAM,SAAS,IAAI,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAClE,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,WAAW,CAAC,SAAS,CAAwC,CAAC;YAC1E,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,OAAO;gBAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;QACtB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,IAAI,QAA8B,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,QAAQ,KAAK,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAC5F,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,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,cAAc,EAAE,CAAC;SACzB,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;SACnD,MAAM,CAAC,OAAO,EAAE,mCAAmC,CAAC;SACpD,MAAM,CAAC,aAAa,EAAE,sEAAsE,CAAC;QAC9F,6FAA6F;SAC5F,aAAa,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;SACxC,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;SACD,IAAI,CAAC,YAAY,EAAE,CAAC,WAAW,EAAE,EAAE;QAClC,0FAA0F;QAC1F,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,GAAG,CAAC;YAAE,OAAO;QAC3F,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEL,6GAA6G;IAC7G,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,14 @@ export interface CreditUsage {
|
|
|
20
20
|
export declare function takeCreditUsage(): CreditUsage | null;
|
|
21
21
|
export declare function formatCreditUsage(usage: CreditUsage): string;
|
|
22
22
|
export declare function apiGet<T = unknown>(opts: RequestOptions): Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* A key-authorized byte stream (`GET /v1/sec/exports/{export_id}/file`): the raw `Response` for the caller to stream
|
|
25
|
+
* and verify, credits recorded, a refusal thrown as `ApiError` like every other request. `signal` aborts it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function apiDownload(opts: RequestOptions & {
|
|
28
|
+
accept: string;
|
|
29
|
+
signal?: AbortSignal;
|
|
30
|
+
}): Promise<Response>;
|
|
23
31
|
export interface ApiRequestOptions extends RequestOptions {
|
|
24
32
|
method: 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
25
33
|
/** Sent as JSON. */
|
|
@@ -24,7 +24,7 @@ const stringField = (body, key) => {
|
|
|
24
24
|
};
|
|
25
25
|
async function apiErrorFrom(response) {
|
|
26
26
|
const body = await response.json().catch(() => null);
|
|
27
|
-
return new ApiError(response.status, stringField(body, 'error') ?? (response.statusText || 'Unknown Error'), stringField(body, 'message') ?? `Request failed with status ${response.status}`, parseRetryAfter(response.headers?.get('Retry-After')));
|
|
27
|
+
return new ApiError(response.status, stringField(body, 'error') ?? (response.statusText || 'Unknown Error'), stringField(body, 'message') ?? `Request failed with status ${response.status}`, parseRetryAfter(response.headers?.get('Retry-After')), stringField(body, 'code'), body ?? undefined);
|
|
28
28
|
}
|
|
29
29
|
let creditUsage = null;
|
|
30
30
|
function recordCredits(response) {
|
|
@@ -80,6 +80,21 @@ export async function apiGet(opts) {
|
|
|
80
80
|
throw error;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* A key-authorized byte stream (`GET /v1/sec/exports/{export_id}/file`): the raw `Response` for the caller to stream
|
|
85
|
+
* and verify, credits recorded, a refusal thrown as `ApiError` like every other request. `signal` aborts it.
|
|
86
|
+
*/
|
|
87
|
+
export async function apiDownload(opts) {
|
|
88
|
+
const url = buildUrl(opts.path, opts.params);
|
|
89
|
+
const headers = { 'Accept': opts.accept };
|
|
90
|
+
if (opts.auth !== false)
|
|
91
|
+
headers['Authorization'] = `Bearer ${await getApiKey()}`;
|
|
92
|
+
const response = await fetch(url, { headers, ...(opts.signal ? { signal: opts.signal } : {}) });
|
|
93
|
+
recordCredits(response);
|
|
94
|
+
if (!response.ok)
|
|
95
|
+
throw await apiErrorFrom(response);
|
|
96
|
+
return response;
|
|
97
|
+
}
|
|
83
98
|
/** A write with a JSON body; same auth / `ApiError` handling as `apiGet`. A 204 / empty body → `undefined`. */
|
|
84
99
|
export async function apiRequest(opts) {
|
|
85
100
|
const spinner = opts.silent ? null : createSpinner('Sending request...');
|
|
@@ -1 +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,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAWrD,SAAS,QAAQ,CAAC,IAAY,EAAE,MAAiC;IAC/D,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,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1D,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;oBACtC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,IAAa,EAAE,GAAW,EAAsB,EAAE;IACrE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvE,CAAC,CAAC;AAEF,KAAK,UAAU,YAAY,CAAC,QAAkB;IAC5C,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,QAAQ,CACjB,QAAQ,CAAC,MAAM,EACf,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,eAAe,CAAC,EACtE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,8BAA8B,QAAQ,CAAC,MAAM,EAAE,EAC/E,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../../src/client/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,39 @@ export declare function downloadToFile(url: string, file: string, opts?: SaveOpt
|
|
|
12
12
|
path: string;
|
|
13
13
|
bytes: number;
|
|
14
14
|
}>;
|
|
15
|
+
/** What the API stated about the bytes; each stated value is verified, an absent one is not. */
|
|
16
|
+
export interface ExpectedFile {
|
|
17
|
+
/** Lower-case hex SHA-256 (also checked against the answer's `X-Content-SHA256` header when it sends one). */
|
|
18
|
+
sha256?: string;
|
|
19
|
+
/** The true size in bytes (else the answer's `Content-Length`, unless the body is content-encoded). */
|
|
20
|
+
bytes?: number;
|
|
21
|
+
/** Accepted media types (parameters ignored); the answer's `Content-Type` must be one of them. */
|
|
22
|
+
contentTypes?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export interface VerifiedFile {
|
|
25
|
+
path: string;
|
|
26
|
+
bytes: number;
|
|
27
|
+
sha256: string;
|
|
28
|
+
/** The target already held exactly these bytes (`expected.sha256` matched): nothing was requested or written. */
|
|
29
|
+
skipped: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Hex SHA-256 of a file on disk. */
|
|
32
|
+
export declare function fileSha256(path: string): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Streams `open(signal)`'s body to `file` through `writeViaPart`, verifying what is known before the rename: the
|
|
35
|
+
* media type, the size (short = `PartialDownloadError`, exit 4; a broken stream too) and the SHA-256 (else
|
|
36
|
+
* `IntegrityError`, exit 5) — a failed check saves nothing. Resume rule for immutable files: an existing target whose
|
|
37
|
+
* SHA-256 equals `expected.sha256` is complete (`skipped`, no request); any other existing target needs `force`.
|
|
38
|
+
* `open` is the request: keyless `fetch` of a permanent public URL, or `apiDownload` for a key-authorized stream.
|
|
39
|
+
*/
|
|
40
|
+
export declare function saveVerified(open: (signal: AbortSignal) => Promise<Response>, file: string, opts?: SaveOptions & {
|
|
41
|
+
expected?: ExpectedFile;
|
|
42
|
+
spinnerText?: string;
|
|
43
|
+
}): Promise<VerifiedFile>;
|
|
44
|
+
/** A file name from a server or manifest, reduced to one safe path segment (no directories, no control chars). */
|
|
45
|
+
export declare function safeFileName(name: string | null | undefined, fallback: string): string;
|
|
46
|
+
/** The `filename` of a `Content-Disposition` header (`filename*=UTF-8''…` first), if any. */
|
|
47
|
+
export declare function dispositionFileName(header: string | null | undefined): string | undefined;
|
|
15
48
|
/** Writes text (transcript, press release) to `file`; refuses an existing target unless `force`. */
|
|
16
49
|
export declare function writeTextFile(file: string, text: string, opts?: SaveOptions): Promise<{
|
|
17
50
|
path: string;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createReadStream, createWriteStream, rmSync } from 'node:fs';
|
|
2
3
|
import { access, mkdir, rename, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
4
|
import { dirname, resolve } from 'node:path';
|
|
4
5
|
import { Readable } from 'node:stream';
|
|
6
|
+
import { Transform } from 'node:stream';
|
|
5
7
|
import { pipeline } from 'node:stream/promises';
|
|
8
|
+
import { IntegrityError, PartialDownloadError } from '../shared/errors.js';
|
|
6
9
|
import { createSpinner } from '../shared/spinner.js';
|
|
7
10
|
async function exists(path) {
|
|
8
11
|
try {
|
|
@@ -77,6 +80,103 @@ export async function downloadToFile(url, file, opts = {}) {
|
|
|
77
80
|
throw error;
|
|
78
81
|
}
|
|
79
82
|
}
|
|
83
|
+
/** Hex SHA-256 of a file on disk. */
|
|
84
|
+
export async function fileSha256(path) {
|
|
85
|
+
const hash = createHash('sha256');
|
|
86
|
+
await pipeline(createReadStream(path), hash);
|
|
87
|
+
return hash.digest('hex');
|
|
88
|
+
}
|
|
89
|
+
const mediaType = (value) => (value ?? '').split(';')[0].trim().toLowerCase();
|
|
90
|
+
/**
|
|
91
|
+
* Streams `open(signal)`'s body to `file` through `writeViaPart`, verifying what is known before the rename: the
|
|
92
|
+
* media type, the size (short = `PartialDownloadError`, exit 4; a broken stream too) and the SHA-256 (else
|
|
93
|
+
* `IntegrityError`, exit 5) — a failed check saves nothing. Resume rule for immutable files: an existing target whose
|
|
94
|
+
* SHA-256 equals `expected.sha256` is complete (`skipped`, no request); any other existing target needs `force`.
|
|
95
|
+
* `open` is the request: keyless `fetch` of a permanent public URL, or `apiDownload` for a key-authorized stream.
|
|
96
|
+
*/
|
|
97
|
+
export async function saveVerified(open, file, opts = {}) {
|
|
98
|
+
const path = resolve(file);
|
|
99
|
+
const expected = opts.expected ?? {};
|
|
100
|
+
if (!opts.force && await exists(path)) {
|
|
101
|
+
if (expected.sha256 && await fileSha256(path) === expected.sha256.toLowerCase()) {
|
|
102
|
+
const { size } = await stat(path);
|
|
103
|
+
return { path, bytes: size, sha256: expected.sha256.toLowerCase(), skipped: true };
|
|
104
|
+
}
|
|
105
|
+
throw new Error(`${path} already exists (use --force to overwrite${expected.sha256 ? '' : ', or pass --sha256 to accept an identical file'})`);
|
|
106
|
+
}
|
|
107
|
+
await mkdir(dirname(path), { recursive: true });
|
|
108
|
+
const spinner = createSpinner(opts.spinnerText ?? 'Downloading...');
|
|
109
|
+
let digest = '';
|
|
110
|
+
let received = 0;
|
|
111
|
+
try {
|
|
112
|
+
await writeViaPart(path, async (part, signal) => {
|
|
113
|
+
const response = await open(signal);
|
|
114
|
+
if (!response.ok || !response.body)
|
|
115
|
+
throw new Error(`Download failed with status ${response.status}`);
|
|
116
|
+
const type = mediaType(response.headers?.get('Content-Type'));
|
|
117
|
+
if (expected.contentTypes && !expected.contentTypes.includes(type)) {
|
|
118
|
+
throw new IntegrityError(`Expected ${expected.contentTypes.join(' or ')}, the server sent ${type || 'no media type'}; nothing was saved`);
|
|
119
|
+
}
|
|
120
|
+
const length = response.headers?.get('Content-Encoding') ? null : response.headers?.get('Content-Length');
|
|
121
|
+
const size = expected.bytes ?? (length && /^\d+$/.test(length) ? Number(length) : undefined);
|
|
122
|
+
const shas = [expected.sha256, response.headers?.get('X-Content-SHA256') ?? undefined]
|
|
123
|
+
.filter((value) => Boolean(value))
|
|
124
|
+
.map(value => value.toLowerCase());
|
|
125
|
+
const hash = createHash('sha256');
|
|
126
|
+
const meter = new Transform({
|
|
127
|
+
transform(chunk, _encoding, done) {
|
|
128
|
+
received += chunk.length;
|
|
129
|
+
hash.update(chunk);
|
|
130
|
+
done(null, chunk);
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
try {
|
|
134
|
+
await pipeline(Readable.fromWeb(response.body), meter, createWriteStream(part), { signal });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (signal.aborted)
|
|
138
|
+
throw error;
|
|
139
|
+
throw new PartialDownloadError(received, size);
|
|
140
|
+
}
|
|
141
|
+
if (size !== undefined && received < size)
|
|
142
|
+
throw new PartialDownloadError(received, size);
|
|
143
|
+
if (size !== undefined && received > size) {
|
|
144
|
+
throw new IntegrityError(`Received ${received} bytes, ${size} were stated; nothing was saved`);
|
|
145
|
+
}
|
|
146
|
+
digest = hash.digest('hex');
|
|
147
|
+
const mismatch = shas.find(sha => sha !== digest);
|
|
148
|
+
if (mismatch)
|
|
149
|
+
throw new IntegrityError(`SHA-256 ${digest} differs from the stated ${mismatch}; nothing was saved`);
|
|
150
|
+
});
|
|
151
|
+
spinner.succeed('Downloaded');
|
|
152
|
+
return { path, bytes: received, sha256: digest, skipped: false };
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
spinner.fail('Download failed');
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** A file name from a server or manifest, reduced to one safe path segment (no directories, no control chars). */
|
|
160
|
+
export function safeFileName(name, fallback) {
|
|
161
|
+
const base = (name ?? '').split(/[\\/]/).pop() ?? '';
|
|
162
|
+
const cleaned = base.replace(/[\u0000-\u001f\u007f<>:"|?*]/g, '_').replace(/^\.+/, '').trim();
|
|
163
|
+
return cleaned && cleaned !== '.' && cleaned !== '..' ? cleaned.slice(0, 200) : fallback;
|
|
164
|
+
}
|
|
165
|
+
/** The `filename` of a `Content-Disposition` header (`filename*=UTF-8''…` first), if any. */
|
|
166
|
+
export function dispositionFileName(header) {
|
|
167
|
+
if (!header)
|
|
168
|
+
return undefined;
|
|
169
|
+
const extended = /filename\*\s*=\s*UTF-8''([^;]+)/i.exec(header)?.[1];
|
|
170
|
+
if (extended) {
|
|
171
|
+
try {
|
|
172
|
+
return decodeURIComponent(extended.trim());
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// fall through to the plain form
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return /filename\s*=\s*"?([^";]+)"?/i.exec(header)?.[1]?.trim();
|
|
179
|
+
}
|
|
80
180
|
/** Writes text (transcript, press release) to `file`; refuses an existing target unless `force`. */
|
|
81
181
|
export async function writeTextFile(file, text, opts = {}) {
|
|
82
182
|
const path = await prepareTarget(file, opts);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/client/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../src/client/download.ts"],"names":[],"mappings":"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"}
|