@invinite-org/invinite-data-cli 0.1.21 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +314 -6
  2. package/claude-plugin/.claude-plugin/plugin.json +13 -5
  3. package/claude-plugin/.mcp.json +8 -0
  4. package/claude-plugin/agents/invinite-data.md +6 -2
  5. package/claude-plugin/commands/analyze-earnings-call.md +24 -0
  6. package/claude-plugin/commands/analyze-filing.md +15 -0
  7. package/claude-plugin/commands/compare-companies.md +15 -0
  8. package/claude-plugin/commands/financial-research.md +2 -1
  9. package/claude-plugin/commands/ownership-review.md +14 -0
  10. package/claude-plugin/skills/invinite-data-cli/SKILL.md +119 -8
  11. package/dist/src/cli.d.ts +2 -0
  12. package/dist/src/cli.js +22 -1
  13. package/dist/src/cli.js.map +1 -1
  14. package/dist/src/client/api-client.d.ts +13 -1
  15. package/dist/src/client/api-client.js +46 -13
  16. package/dist/src/client/api-client.js.map +1 -1
  17. package/dist/src/client/download.d.ts +23 -0
  18. package/dist/src/client/download.js +116 -0
  19. package/dist/src/client/download.js.map +1 -0
  20. package/dist/src/client/earnings-live.d.ts +79 -0
  21. package/dist/src/client/earnings-live.js +156 -0
  22. package/dist/src/client/earnings-live.js.map +1 -0
  23. package/dist/src/client/pagination.js +2 -1
  24. package/dist/src/client/pagination.js.map +1 -1
  25. package/dist/src/client/websocket-client.d.ts +12 -1
  26. package/dist/src/client/websocket-client.js +114 -37
  27. package/dist/src/client/websocket-client.js.map +1 -1
  28. package/dist/src/commands/earnings-selector.d.ts +15 -0
  29. package/dist/src/commands/earnings-selector.js +29 -0
  30. package/dist/src/commands/earnings-selector.js.map +1 -0
  31. package/dist/src/commands/earnings.d.ts +13 -0
  32. package/dist/src/commands/earnings.js +705 -0
  33. package/dist/src/commands/earnings.js.map +1 -0
  34. package/dist/src/commands/plugin.d.ts +11 -0
  35. package/dist/src/commands/plugin.js +23 -8
  36. package/dist/src/commands/plugin.js.map +1 -1
  37. package/dist/src/commands/webhooks.d.ts +6 -0
  38. package/dist/src/commands/webhooks.js +144 -0
  39. package/dist/src/commands/webhooks.js.map +1 -0
  40. package/dist/src/commands/ws.js +23 -3
  41. package/dist/src/commands/ws.js.map +1 -1
  42. package/dist/src/formatters/flatten.d.ts +4 -0
  43. package/dist/src/formatters/flatten.js +15 -0
  44. package/dist/src/formatters/flatten.js.map +1 -0
  45. package/dist/src/formatters/time.d.ts +2 -0
  46. package/dist/src/formatters/time.js +14 -0
  47. package/dist/src/formatters/time.js.map +1 -0
  48. package/dist/src/shared/errors.d.ts +2 -1
  49. package/dist/src/shared/errors.js +5 -1
  50. package/dist/src/shared/errors.js.map +1 -1
  51. package/dist/src/shared/options.d.ts +2 -0
  52. package/dist/src/shared/options.js +6 -0
  53. package/dist/src/shared/options.js.map +1 -1
  54. package/package.json +1 -1
@@ -0,0 +1,156 @@
1
+ import chalk from 'chalk';
2
+ import { formatMs } from '../formatters/time.js';
3
+ /**
4
+ * Pure pieces of `invd ws listen --earnings`: the subscribe frame and one step per server
5
+ * frame of IDA's `earnings-calls.live` channel (`src/routes/websocket/types/earningsMessages.ts`).
6
+ */
7
+ export const EARNINGS_LIVE_CHANNEL = 'earnings-calls.live';
8
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
9
+ /** Ends the run with exit 1. */
10
+ const FATAL_ERRORS = new Set(['forbidden_tier', 'not_live', 'not_found', 'subscription_limit', 'bad_message']);
11
+ /** Retried through the reconnect backoff. */
12
+ const RETRY_ERRORS = new Set(['attach_failed', 'unavailable']);
13
+ /** `--earnings`: a UUID is an event_id, 1–10 digits a CIK. */
14
+ export function parseTarget(value) {
15
+ const target = value.trim();
16
+ if (UUID_RE.test(target))
17
+ return { event_id: target.toLowerCase() };
18
+ if (/^\d{1,10}$/.test(target))
19
+ return { cik: target };
20
+ throw new Error('--earnings takes an event ID (UUID) or a CIK (digits)');
21
+ }
22
+ /** `--since-seq`: an integer ≥ -1; default -1 (the whole call from its first final). */
23
+ export function parseSinceSeq(value) {
24
+ if (value === undefined)
25
+ return -1;
26
+ const seq = Number(value);
27
+ if (!Number.isInteger(seq) || seq < -1)
28
+ throw new Error('--since-seq takes an integer ≥ -1');
29
+ return seq;
30
+ }
31
+ export function subscribeFrame(target, sinceSeq, partials) {
32
+ return { type: 'subscribe', channel: EARNINGS_LIVE_CHANNEL, ...target, since_seq: sinceSeq, partials };
33
+ }
34
+ export function initialLiveState(sinceSeq) {
35
+ return { lastSeq: sinceSeq, eventId: null, names: null };
36
+ }
37
+ /** The assignment of `label` covering `seq` (the latest-starting one wins), else null. */
38
+ export function nameFor(assignments, label, seq) {
39
+ let best = null;
40
+ for (const a of assignments) {
41
+ if (a.speaker_label !== label || a.from_seq > seq || (a.to_seq !== null && seq > a.to_seq))
42
+ continue;
43
+ if (!best || a.from_seq > best.from_seq)
44
+ best = a;
45
+ }
46
+ return best?.name ?? null;
47
+ }
48
+ /** `[m:ss] name: text`, the name from the snapshot, else `Speaker <label>`. */
49
+ export function formatSegment(segment, assignments) {
50
+ const name = nameFor(assignments, segment.speaker_label, segment.seq)
51
+ ?? (segment.speaker_label === null ? 'Speaker' : `Speaker ${segment.speaker_label}`);
52
+ return `[${formatMs(segment.start_ms)}] ${name}: ${segment.text}`;
53
+ }
54
+ export function finalTranscriptHint(eventId) {
55
+ return `final transcript: invd earnings transcript --event ${eventId ?? '<event_id>'}`;
56
+ }
57
+ /** IDA `UNSUBSCRIBE_REASONS` → the closing line; the transcript hint only where a transcript follows. */
58
+ function unsubscribedNote(reason, eventId) {
59
+ switch (reason) {
60
+ case 'transcript_ready':
61
+ return finalTranscriptHint(eventId);
62
+ case 'rescheduled':
63
+ return 'the call was rescheduled; listen again at the new time';
64
+ case 'no_transcript':
65
+ return `no final transcript yet; check later with: invd earnings transcript --event ${eventId ?? '<event_id>'}`;
66
+ default:
67
+ return 'this call produces no more live segments';
68
+ }
69
+ }
70
+ function namesLines(revision, assignments) {
71
+ return [
72
+ chalk.dim(`speaker names (revision ${revision})`),
73
+ ...assignments.map(a => {
74
+ const detail = [a.title, a.firm].filter(Boolean).join(', ');
75
+ const range = `seq ${a.from_seq}–${a.to_seq ?? '…'}`;
76
+ return chalk.dim(` ${a.speaker_label} → ${a.name}${detail ? ` (${detail})` : ''}${a.role ? ` [${a.role}]` : ''} ${range}`);
77
+ }),
78
+ ];
79
+ }
80
+ /** One server frame → the new state and what to print / do. Unknown frames are ignored. */
81
+ export function liveStep(state, frame, opts) {
82
+ switch (frame.type) {
83
+ case 'subscribed': {
84
+ const latest = frame.current_seq === null ? 'none yet' : `latest ${frame.current_seq}`;
85
+ return {
86
+ state: { ...state, eventId: frame.event_id },
87
+ lines: [chalk.bold(`${frame.symbol} ${frame.conference_date} · ${frame.state} · from seq ${state.lastSeq + 1} (${latest})`)],
88
+ };
89
+ }
90
+ case 'transcript_segment': {
91
+ const assignments = state.names?.assignments ?? [];
92
+ if (!frame.is_final) {
93
+ return opts.partials ? { state, lines: [], partial: chalk.dim(formatSegment(frame, assignments)) } : { state, lines: [] };
94
+ }
95
+ return {
96
+ state: { ...state, lastSeq: Math.max(state.lastSeq, frame.seq) },
97
+ lines: [formatSegment(frame, assignments)],
98
+ };
99
+ }
100
+ case 'speaker_names': {
101
+ if (state.names && frame.revision <= state.names.revision)
102
+ return { state, lines: [] };
103
+ const names = { revision: frame.revision, assignments: frame.assignments ?? [] };
104
+ return { state: { ...state, names }, lines: opts.names ? namesLines(names.revision, names.assignments) : [] };
105
+ }
106
+ // `gap` and `resume_unavailable` are notes only — never a re-subscribe. Verified against IDA
107
+ // (invinite-data-api, 2026-10-10): a final inside a reported gap is still delivered once on
108
+ // the SAME subscription (`deliverFinal`, src/lib/earningsLiveBridge.ts:462-476), and so are
109
+ // gaps of a `since_seq` replay (`recordReportedGaps`, src/routes/websocket/earningsSubscriptions.ts:273).
110
+ // `resume_unavailable` is sent after a successful `subscribed` (earningsSubscriptions.ts:286-293);
111
+ // live delivery continues, and once the call's Ably history becomes readable the bridge
112
+ // back-fills missed finals into the existing subscriptions (`repass`, earningsLiveBridge.ts:660-690).
113
+ // A second subscribe would replay from the same ring and add a duplicate subscription.
114
+ case 'gap':
115
+ return { state, lines: [chalk.dim(`gap after seq ${frame.after_seq} (next ${frame.next_seq}); late segments still arrive`)] };
116
+ case 'call_started':
117
+ return { state, lines: [chalk.bold(`call started ${frame.at}`)] };
118
+ case 'call_ended':
119
+ return { state, lines: [chalk.bold(`call ended ${frame.at}`)] };
120
+ case 'transcript_provisional':
121
+ return { state, lines: [chalk.bold(`provisional transcript v${frame.version} (${frame.word_count} words, speakers not named yet)`)] };
122
+ case 'rescheduled':
123
+ return { state, lines: [chalk.bold(`rescheduled to ${frame.new_conference_date}`)] };
124
+ case 'transcript_ready':
125
+ return {
126
+ state,
127
+ lines: [chalk.bold(`transcript ready ${frame.at}`)],
128
+ end: { code: 0, message: finalTranscriptHint(state.eventId) },
129
+ };
130
+ case 'unsubscribed':
131
+ return {
132
+ state,
133
+ lines: [chalk.bold(`subscription ended: ${frame.reason}`)],
134
+ end: { code: 0, message: unsubscribedNote(frame.reason, state.eventId) },
135
+ };
136
+ case 'error': {
137
+ if (frame.code === 'resume_unavailable') {
138
+ return { state, lines: [chalk.dim('missed segments cannot be replayed for this call; live delivery continues')] };
139
+ }
140
+ if (RETRY_ERRORS.has(frame.code)) {
141
+ return { state, lines: [chalk.dim(`${frame.code}: ${frame.message}; retrying`)], reconnect: true };
142
+ }
143
+ const message = frame.code === 'forbidden_tier'
144
+ ? `earnings-calls.live needs the PRO plan (${frame.message})`
145
+ : `${frame.code}: ${frame.message}`;
146
+ return { state, lines: [], end: { code: 1, message: FATAL_ERRORS.has(frame.code) ? message : `${message} (unknown error code)` } };
147
+ }
148
+ default:
149
+ return { state, lines: [] };
150
+ }
151
+ }
152
+ /** Frames of the earnings channel (the socket also carries `new_filing` broadcasts and pings). */
153
+ export function isEarningsFrame(frame) {
154
+ return frame.type === 'error' || frame.type === 'unsubscribed' || typeof frame.subscription_id === 'string';
155
+ }
156
+ //# sourceMappingURL=earnings-live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"earnings-live.js","sourceRoot":"","sources":["../../../src/client/earnings-live.ts"],"names":[],"mappings":"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"}
@@ -10,8 +10,9 @@ export async function fetchAllPages(initialData, extractNextUrl, mergeResults) {
10
10
  try {
11
11
  // nextUrl is absolute, extract path+query
12
12
  const url = new URL(nextUrl);
13
+ // Repeated keys (`status=a&status=b`) stay repeated.
13
14
  const params = {};
14
- url.searchParams.forEach((v, k) => { params[k] = v; });
15
+ url.searchParams.forEach((v, k) => { (params[k] ??= []).push(v); });
15
16
  const pageData = await apiGet({ path: url.pathname, params, silent: true });
16
17
  result = mergeResults(result, pageData);
17
18
  nextUrl = extractNextUrl(pageData);
@@ -1 +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"}
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,qDAAqD;YACrD,MAAM,MAAM,GAA6B,EAAE,CAAC;YAC5C,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,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"}
@@ -1 +1,12 @@
1
- export declare function connectWebSocket(): Promise<void>;
1
+ import { type LiveTarget } from './earnings-live.js';
2
+ export interface EarningsListenOptions {
3
+ target: LiveTarget;
4
+ sinceSeq: number;
5
+ partials: boolean;
6
+ names: boolean;
7
+ /** NDJSON: every earnings frame as one line, nothing else on stdout. */
8
+ json: boolean;
9
+ }
10
+ export declare function connectWebSocket(opts?: {
11
+ earnings?: EarningsListenOptions;
12
+ }): Promise<void>;
@@ -1,57 +1,134 @@
1
1
  import { getApiKey } from '../config/auth.js';
2
2
  import { getBaseUrl } from '../config/config-manager.js';
3
3
  import chalk from 'chalk';
4
- export async function connectWebSocket() {
4
+ import { initialLiveState, isEarningsFrame, liveStep, subscribeFrame, } from './earnings-live.js';
5
+ /** Close codes of `/v1/ws` that a reconnect cannot fix (bad key, plan, connection limit). */
6
+ const PERMANENT_CLOSE_CODES = new Set([4001, 4003, 4029]);
7
+ const CLEAR_LINE = '\r\x1b[2K';
8
+ export async function connectWebSocket(opts = {}) {
5
9
  const apiKey = await getApiKey();
6
10
  const base = getBaseUrl().replace(/\/+$/, '').replace(/^http/, 'ws');
7
11
  const url = `${base}/v1/ws?api_key=${encodeURIComponent(apiKey)}`;
12
+ const earnings = opts.earnings;
13
+ const status = (line) => {
14
+ if (!earnings?.json)
15
+ console.log(line);
16
+ };
8
17
  let reconnectDelay = 1000;
9
18
  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}`));
19
+ let current = null;
20
+ let live = earnings ? initialLiveState(earnings.sinceSeq) : null;
21
+ let partialShown = false;
22
+ return new Promise((resolve, reject) => {
23
+ function clearPartial() {
24
+ if (partialShown) {
25
+ process.stdout.write(CLEAR_LINE);
26
+ partialShown = false;
27
+ }
28
+ }
29
+ function finish(error) {
30
+ shouldReconnect = false;
31
+ clearPartial();
32
+ current?.close();
33
+ if (error)
34
+ reject(error);
35
+ else
36
+ resolve();
37
+ }
38
+ function handleEarnings(ws, data) {
39
+ if (!earnings || !live || !isEarningsFrame(data))
40
+ return;
41
+ if (earnings.json)
42
+ console.log(JSON.stringify(data));
43
+ const step = liveStep(live, data, earnings);
44
+ live = step.state;
45
+ if (!earnings.json) {
46
+ if (step.lines.length)
47
+ clearPartial();
48
+ for (const line of step.lines)
49
+ console.log(line);
50
+ if (step.partial && process.stdout.isTTY) {
51
+ const width = (process.stdout.columns ?? 80) - 1;
52
+ process.stdout.write(CLEAR_LINE + step.partial.slice(0, width));
53
+ partialShown = true;
54
+ }
55
+ }
56
+ if (step.end) {
57
+ if (step.end.code === 0) {
58
+ status(chalk.dim(step.end.message));
59
+ finish();
27
60
  }
28
61
  else {
29
- console.log(JSON.stringify(data, null, 2));
62
+ finish(new Error(step.end.message));
30
63
  }
31
64
  }
32
- catch {
33
- console.log(String(event.data));
65
+ else if (step.reconnect) {
66
+ ws.close();
34
67
  }
35
- });
36
- ws.addEventListener('close', () => {
37
- if (shouldReconnect) {
38
- console.log(chalk.yellow(`Disconnected. Reconnecting in ${reconnectDelay / 1000}s...`));
68
+ }
69
+ function connect() {
70
+ status(chalk.dim('Connecting to WebSocket...'));
71
+ const ws = new WebSocket(url);
72
+ current = ws;
73
+ ws.addEventListener('open', () => {
74
+ reconnectDelay = 1000;
75
+ if (earnings && live) {
76
+ status(chalk.green(`Connected; subscribing to ${earnings.partials ? 'live transcript + partials' : 'live transcript'}`));
77
+ // A reconnect resumes after the last printed final (the API replays the gap).
78
+ ws.send(JSON.stringify(subscribeFrame(earnings.target, live.lastSeq, earnings.partials)));
79
+ }
80
+ else {
81
+ console.log(chalk.green('Connected to filing stream'));
82
+ }
83
+ });
84
+ ws.addEventListener('message', (event) => {
85
+ try {
86
+ const data = JSON.parse(String(event.data));
87
+ if (data.type === 'ping')
88
+ return;
89
+ if (earnings) {
90
+ handleEarnings(ws, data);
91
+ }
92
+ else if (data.type === 'new_filing') {
93
+ const f = data.filing;
94
+ console.log(chalk.bold(`[${f.form_type}]`) + ` ${f.cik} - Filed ${f.filing_date}`);
95
+ if (f.html_url)
96
+ console.log(chalk.dim(` ${f.html_url}`));
97
+ }
98
+ else {
99
+ console.log(JSON.stringify(data, null, 2));
100
+ }
101
+ }
102
+ catch {
103
+ if (!earnings)
104
+ console.log(String(event.data));
105
+ }
106
+ });
107
+ ws.addEventListener('close', (event) => {
108
+ if (!shouldReconnect)
109
+ return;
110
+ if (PERMANENT_CLOSE_CODES.has(event.code)) {
111
+ finish(new Error(`WebSocket closed (${event.code}): ${event.reason || 'refused'}`));
112
+ return;
113
+ }
114
+ clearPartial();
115
+ status(chalk.yellow(`Disconnected. Reconnecting in ${reconnectDelay / 1000}s...`));
39
116
  setTimeout(connect, reconnectDelay);
40
117
  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', () => {
118
+ });
119
+ ws.addEventListener('error', (error) => {
120
+ if (!earnings?.json)
121
+ console.error(chalk.red('WebSocket error:'), error);
122
+ });
123
+ }
124
+ process.once('SIGINT', () => {
47
125
  shouldReconnect = false;
48
- ws.close();
49
- console.log(chalk.dim('\nDisconnected.'));
126
+ clearPartial();
127
+ current?.close();
128
+ status(chalk.dim('\nDisconnected.'));
50
129
  process.exit(0);
51
130
  });
52
- }
53
- connect();
54
- // Keep process alive
55
- await new Promise(() => { });
131
+ connect();
132
+ });
56
133
  }
57
134
  //# sourceMappingURL=websocket-client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../../../src/client/websocket-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../../../src/client/websocket-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Command } from 'commander';
2
+ /** IDA's own wording (`eventSelectorSchema`) for an incomplete selector. */
3
+ export declare const SELECTOR_MESSAGE = "Provide event_id, or identifier with year+quarter or date";
4
+ export interface SelectorOptions {
5
+ event?: string;
6
+ identifier?: string;
7
+ year?: string;
8
+ quarter?: string;
9
+ date?: string;
10
+ }
11
+ /** Adds the event selector: `--event <uuid>`, or `-i` with `--year` + `--quarter` or `--date`. */
12
+ export declare function selectorOptions(cmd: Command): Command;
13
+ export declare function selectorParams(opts: SelectorOptions): Record<string, string | undefined>;
14
+ /** Throws (→ `withErrorHandling` exits 1) unless one selector form is complete. */
15
+ export declare function validateSelector(opts: SelectorOptions): void;
@@ -0,0 +1,29 @@
1
+ /** IDA's own wording (`eventSelectorSchema`) for an incomplete selector. */
2
+ export const SELECTOR_MESSAGE = 'Provide event_id, or identifier with year+quarter or date';
3
+ /** Adds the event selector: `--event <uuid>`, or `-i` with `--year` + `--quarter` or `--date`. */
4
+ export function selectorOptions(cmd) {
5
+ return cmd
6
+ .option('--event <event_id>', 'Event ID (wins over the other selectors)')
7
+ .option('-i, --identifier <ticker>', 'Ticker or CIK (with --year + --quarter, or --date)')
8
+ .option('--year <n>', 'Fiscal year of the call (with --quarter)')
9
+ .option('--quarter <n>', 'Fiscal quarter of the call (with --year)')
10
+ .option('--date <date>', 'New York calendar day of the call (YYYY-MM-DD)');
11
+ }
12
+ export function selectorParams(opts) {
13
+ return {
14
+ event_id: opts.event,
15
+ identifier: opts.identifier,
16
+ year: opts.year,
17
+ quarter: opts.quarter,
18
+ date: opts.date,
19
+ };
20
+ }
21
+ /** Throws (→ `withErrorHandling` exits 1) unless one selector form is complete. */
22
+ export function validateSelector(opts) {
23
+ if (opts.event)
24
+ return;
25
+ if (opts.identifier && ((opts.year && opts.quarter) || opts.date))
26
+ return;
27
+ throw new Error(SELECTOR_MESSAGE);
28
+ }
29
+ //# sourceMappingURL=earnings-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"earnings-selector.js","sourceRoot":"","sources":["../../../src/commands/earnings-selector.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,2DAA2D,CAAC;AAU5F,kGAAkG;AAClG,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,OAAO,GAAG;SACP,MAAM,CAAC,oBAAoB,EAAE,0CAA0C,CAAC;SACxE,MAAM,CAAC,2BAA2B,EAAE,oDAAoD,CAAC;SACzF,MAAM,CAAC,YAAY,EAAE,0CAA0C,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,0CAA0C,CAAC;SACnE,MAAM,CAAC,eAAe,EAAE,gDAAgD,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAqB;IAClD,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,KAAK;QACpB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,IAAqB;IACpD,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO;IACvB,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO;IAC1E,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { Command } from 'commander';
2
+ import { ApiError } from '../shared/errors.js';
3
+ type Row = Record<string, any>;
4
+ /** One dim line after a 403 whose message names the plan the route needs. */
5
+ export declare function planHint(error: ApiError): string | undefined;
6
+ /** "Q&A starts at m:ss" for the transcript header; undefined without a Q&A boundary. */
7
+ export declare function qaStartLine(qaStartMs: unknown): string | undefined;
8
+ /** Plain-text rendering of a transcript `data` (console and `--output`); `words` stays JSON. */
9
+ export declare function transcriptText(data: unknown, format: string): string;
10
+ /** `documents --output`: the warning for a document without a signed URL. */
11
+ export declare function skippedDocumentWarning(doc: Row): string;
12
+ export declare function registerEarningsCommands(program: Command): void;
13
+ export {};