@teemtape/cli 0.1.2 → 0.1.3
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 +18 -0
- package/dist/index.js +106 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -40,9 +40,25 @@ and `notes` work immediately. Once it's published you'll be able to run it as
|
|
|
40
40
|
| `teemtape add <SYMBOL>` | Add a symbol to your watchlist |
|
|
41
41
|
| `teemtape notes <SYMBOL>` | Read the anonymous note thread for a symbol |
|
|
42
42
|
| `teemtape note <SYMBOL> -m "…"` | Post an anonymous note (tagged `source: cli`) |
|
|
43
|
+
| `teemtape handle [name]` | Show, set, or generate your anonymous handle |
|
|
43
44
|
| `teemtape share` | Print your shareable watchlist link |
|
|
44
45
|
| `teemtape config` | Show resolved config (token masked) |
|
|
45
46
|
|
|
47
|
+
### Anonymous handle
|
|
48
|
+
|
|
49
|
+
So your notes are attributable on a shared watchlist (without signing in), the
|
|
50
|
+
CLI uses a short **handle** like `user1234`. One is auto-generated and saved the
|
|
51
|
+
first time you `init` or post a `note`; change it anytime:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
teemtape handle # show your current handle
|
|
55
|
+
teemtape handle trader_jane # claim a specific handle (must be available)
|
|
56
|
+
teemtape handle --generate # get a fresh, unique handle
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The handle is stored in your config file and becomes the `author` on notes you
|
|
60
|
+
post. It's a display identity, not a credential.
|
|
61
|
+
|
|
46
62
|
### Symbol search
|
|
47
63
|
|
|
48
64
|
Search the SEC symbol catalog (no watchlist token required):
|
|
@@ -59,6 +75,7 @@ teemtape search apple --limit 5 --json
|
|
|
59
75
|
|
|
60
76
|
- `--api-url <url>` — Worker API base URL
|
|
61
77
|
- `--token <token>` — watchlist token
|
|
78
|
+
- `--handle <name>` — anonymous handle for posted notes
|
|
62
79
|
- `--web-url <url>` — web base URL for share links
|
|
63
80
|
- `--json` — machine-readable JSON output (handy for agents)
|
|
64
81
|
|
|
@@ -70,6 +87,7 @@ Resolved with precedence: **CLI flags > env vars > config file > defaults**.
|
|
|
70
87
|
| ------- | ---- | ------- | ------- |
|
|
71
88
|
| API URL | `--api-url` | `TEEMTAPE_API_URL` | `https://api.teemtape.com` |
|
|
72
89
|
| Token | `--token` | `TEEMTAPE_TOKEN` | (none) |
|
|
90
|
+
| Handle | `--handle` | `TEEMTAPE_HANDLE` | (auto-generated on first use) |
|
|
73
91
|
| Web URL | `--web-url` | `TEEMTAPE_WEB_URL` | `https://www.teemtape.com` |
|
|
74
92
|
|
|
75
93
|
The config file lives at `~/.config/teemtape/config.json` (or
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,20 @@ var TeemtapeClient = class {
|
|
|
44
44
|
async createWatchlist() {
|
|
45
45
|
return this.request(`/api/watchlists`, { method: "POST" });
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Claim an anonymous handle. Pass a `handle` to request a specific one (throws
|
|
49
|
+
* ApiError 409 if taken); omit it to get a fresh, unique, auto-generated one.
|
|
50
|
+
*/
|
|
51
|
+
async createHandle(handle) {
|
|
52
|
+
return this.request(`/api/handles`, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
body: JSON.stringify(handle ? { handle } : {})
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Check whether a specific handle is still available (not yet claimed). */
|
|
58
|
+
async checkHandle(handle) {
|
|
59
|
+
return this.request(`/api/handles/${encodeURIComponent(handle)}`);
|
|
60
|
+
}
|
|
47
61
|
/** Fetch a watchlist (symbols + metadata) by token. */
|
|
48
62
|
async getWatchlist(token = this.requireToken()) {
|
|
49
63
|
return this.request(`/api/w/${token}`);
|
|
@@ -258,12 +272,14 @@ function resolveConfig(flags = {}) {
|
|
|
258
272
|
const env = {
|
|
259
273
|
apiUrl: process.env.TEEMTAPE_API_URL,
|
|
260
274
|
webUrl: process.env.TEEMTAPE_WEB_URL,
|
|
261
|
-
token: process.env.TEEMTAPE_TOKEN
|
|
275
|
+
token: process.env.TEEMTAPE_TOKEN,
|
|
276
|
+
handle: process.env.TEEMTAPE_HANDLE
|
|
262
277
|
};
|
|
263
278
|
return {
|
|
264
279
|
apiUrl: flags.apiUrl ?? env.apiUrl ?? file.apiUrl ?? DEFAULTS.apiUrl,
|
|
265
280
|
webUrl: flags.webUrl ?? env.webUrl ?? file.webUrl ?? DEFAULTS.webUrl,
|
|
266
|
-
token: flags.token ?? env.token ?? file.token
|
|
281
|
+
token: flags.token ?? env.token ?? file.token,
|
|
282
|
+
handle: flags.handle ?? env.handle ?? file.handle
|
|
267
283
|
};
|
|
268
284
|
}
|
|
269
285
|
function saveConfig(patch) {
|
|
@@ -286,6 +302,7 @@ async function configCommand(ctx) {
|
|
|
286
302
|
apiUrl: ctx.config.apiUrl,
|
|
287
303
|
webUrl: ctx.config.webUrl,
|
|
288
304
|
token: maskToken(ctx.config.token),
|
|
305
|
+
handle: ctx.config.handle ?? "(none)",
|
|
289
306
|
configFile: configFilePath()
|
|
290
307
|
};
|
|
291
308
|
if (ctx.json) {
|
|
@@ -299,23 +316,100 @@ async function configCommand(ctx) {
|
|
|
299
316
|
process.stdout.write(` web url : ${view.webUrl}
|
|
300
317
|
`);
|
|
301
318
|
process.stdout.write(` token : ${view.token}
|
|
319
|
+
`);
|
|
320
|
+
process.stdout.write(` handle : ${view.handle}
|
|
302
321
|
`);
|
|
303
322
|
process.stdout.write(` ${c.dim(`config file: ${view.configFile}`)}
|
|
304
323
|
`);
|
|
305
324
|
}
|
|
306
325
|
|
|
326
|
+
// src/handle.ts
|
|
327
|
+
var HANDLE_RE = /^[a-z][a-z0-9_-]{2,19}$/;
|
|
328
|
+
function normalizeHandle(raw) {
|
|
329
|
+
return raw.trim().toLowerCase();
|
|
330
|
+
}
|
|
331
|
+
function assertValidHandle(raw) {
|
|
332
|
+
const handle = normalizeHandle(raw);
|
|
333
|
+
if (!HANDLE_RE.test(handle)) {
|
|
334
|
+
throw new Error(
|
|
335
|
+
"invalid handle: use 3-20 characters (letters, numbers, - or _) starting with a letter"
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
return handle;
|
|
339
|
+
}
|
|
340
|
+
async function ensureHandle(ctx) {
|
|
341
|
+
if (ctx.config.handle) return ctx.config.handle;
|
|
342
|
+
const { handle } = await ctx.client.createHandle();
|
|
343
|
+
saveConfig({ handle });
|
|
344
|
+
ctx.config.handle = handle;
|
|
345
|
+
return handle;
|
|
346
|
+
}
|
|
347
|
+
async function setHandle(ctx, requested) {
|
|
348
|
+
const wanted = assertValidHandle(requested);
|
|
349
|
+
const { handle } = await ctx.client.createHandle(wanted);
|
|
350
|
+
saveConfig({ handle });
|
|
351
|
+
ctx.config.handle = handle;
|
|
352
|
+
return handle;
|
|
353
|
+
}
|
|
354
|
+
async function generateHandle(ctx) {
|
|
355
|
+
const { handle } = await ctx.client.createHandle();
|
|
356
|
+
saveConfig({ handle });
|
|
357
|
+
ctx.config.handle = handle;
|
|
358
|
+
return handle;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/commands/handle.ts
|
|
362
|
+
async function handleCommand(ctx, name, opts) {
|
|
363
|
+
if (name) {
|
|
364
|
+
const handle = await setHandle(ctx, name);
|
|
365
|
+
return report(ctx, handle, "claimed");
|
|
366
|
+
}
|
|
367
|
+
if (opts.generate) {
|
|
368
|
+
const handle = await generateHandle(ctx);
|
|
369
|
+
return report(ctx, handle, "generated");
|
|
370
|
+
}
|
|
371
|
+
const current = ctx.config.handle;
|
|
372
|
+
if (ctx.json) {
|
|
373
|
+
printJson({ handle: current ?? null });
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (!current) {
|
|
377
|
+
process.stdout.write(
|
|
378
|
+
`${c.dim("No handle set yet.")} Run ${c.cyan("teemtape handle --generate")} or post a note to get one.
|
|
379
|
+
`
|
|
380
|
+
);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
process.stdout.write(`${c.bold("handle")}: ${c.cyan(current)}
|
|
384
|
+
`);
|
|
385
|
+
}
|
|
386
|
+
function report(ctx, handle, verb) {
|
|
387
|
+
if (ctx.json) {
|
|
388
|
+
printJson({ handle });
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
process.stdout.write(`${c.green("\u2713")} Handle ${verb}: ${c.cyan(handle)}
|
|
392
|
+
`);
|
|
393
|
+
process.stdout.write(` ${c.dim("saved locally \xB7 used as the author on notes you post")}
|
|
394
|
+
`);
|
|
395
|
+
}
|
|
396
|
+
|
|
307
397
|
// src/commands/init.ts
|
|
308
398
|
async function initCommand(ctx) {
|
|
309
399
|
const watchlist = await ctx.client.createWatchlist();
|
|
310
400
|
const path = saveConfig({ token: watchlist.token });
|
|
401
|
+
ctx.config.token = watchlist.token;
|
|
311
402
|
const url = `${ctx.config.webUrl.replace(/\/$/, "")}/w/${watchlist.token}`;
|
|
403
|
+
const handle = await ensureHandle(ctx);
|
|
312
404
|
if (ctx.json) {
|
|
313
|
-
printJson({ token: watchlist.token, url, configPath: path });
|
|
405
|
+
printJson({ token: watchlist.token, handle, url, configPath: path });
|
|
314
406
|
return;
|
|
315
407
|
}
|
|
316
408
|
process.stdout.write(`${c.green("\u2713")} Created a new anonymous watchlist
|
|
317
409
|
`);
|
|
318
410
|
process.stdout.write(` ${c.dim(`token saved to ${path}`)}
|
|
411
|
+
`);
|
|
412
|
+
process.stdout.write(` ${c.dim("handle:")} ${c.cyan(handle)} ${c.dim("(change with `teemtape handle <name>`)")}
|
|
319
413
|
`);
|
|
320
414
|
process.stdout.write(` ${c.dim("share link:")} ${url}
|
|
321
415
|
`);
|
|
@@ -355,7 +449,8 @@ async function noteCommand(ctx, symbol, opts) {
|
|
|
355
449
|
if (!body) {
|
|
356
450
|
throw new Error('A note message is required. Use --message "your note".');
|
|
357
451
|
}
|
|
358
|
-
const
|
|
452
|
+
const handle = await ensureHandle(ctx);
|
|
453
|
+
const note = await ctx.client.addNote({ symbol, body, source: "cli", handle });
|
|
359
454
|
if (ctx.json) {
|
|
360
455
|
printJson(note);
|
|
361
456
|
return;
|
|
@@ -490,12 +585,13 @@ function describeNetworkError(err) {
|
|
|
490
585
|
// src/index.ts
|
|
491
586
|
configureProxyFromEnv();
|
|
492
587
|
var program = new Command();
|
|
493
|
-
program.name("teemtape").description("teemtape \u2014 list stocks and post anonymous notes from the terminal.").version("0.0.0").option("--api-url <url>", "Worker API base URL (env: TEEMTAPE_API_URL)").option("--token <token>", "watchlist token (env: TEEMTAPE_TOKEN)").option("--web-url <url>", "web app base URL used for share links (env: TEEMTAPE_WEB_URL)").option("--json", "output machine-readable JSON (handy for agents)").showHelpAfterError();
|
|
588
|
+
program.name("teemtape").description("teemtape \u2014 list stocks and post anonymous notes from the terminal.").version("0.0.0").option("--api-url <url>", "Worker API base URL (env: TEEMTAPE_API_URL)").option("--token <token>", "watchlist token (env: TEEMTAPE_TOKEN)").option("--handle <name>", "anonymous handle for posted notes (env: TEEMTAPE_HANDLE)").option("--web-url <url>", "web app base URL used for share links (env: TEEMTAPE_WEB_URL)").option("--json", "output machine-readable JSON (handy for agents)").showHelpAfterError();
|
|
494
589
|
function globalsOf(command) {
|
|
495
590
|
const o = command.optsWithGlobals();
|
|
496
591
|
return {
|
|
497
592
|
apiUrl: o.apiUrl,
|
|
498
593
|
token: o.token,
|
|
594
|
+
handle: o.handle,
|
|
499
595
|
webUrl: o.webUrl,
|
|
500
596
|
json: Boolean(o.json)
|
|
501
597
|
};
|
|
@@ -542,6 +638,9 @@ program.command("note").argument("<symbol>", "ticker symbol, e.g. AAPL").require
|
|
|
542
638
|
async (symbol, opts, command) => run(command, (ctx) => noteCommand(ctx, symbol, opts))
|
|
543
639
|
);
|
|
544
640
|
program.command("share").description("print your anonymous shareable watchlist link").action(async (_opts, command) => run(command, (ctx) => shareCommand(ctx)));
|
|
641
|
+
program.command("handle").argument("[name]", "claim a specific handle, e.g. user1234").option("--generate", "generate a fresh, unique handle").description("show, set, or generate your anonymous handle").action(
|
|
642
|
+
async (name, opts, command) => run(command, (ctx) => handleCommand(ctx, name, opts))
|
|
643
|
+
);
|
|
545
644
|
program.command("config").description("show the resolved configuration (token masked)").action(async (_opts, command) => run(command, (ctx) => configCommand(ctx)));
|
|
546
645
|
program.addHelpText(
|
|
547
646
|
"after",
|
|
@@ -555,6 +654,8 @@ Examples:
|
|
|
555
654
|
$ teemtape list
|
|
556
655
|
$ teemtape notes NVDA
|
|
557
656
|
$ teemtape note AAPL --message "Earnings call scheduled."
|
|
657
|
+
$ teemtape handle # show your anonymous handle
|
|
658
|
+
$ teemtape handle trader_jane # claim a specific handle
|
|
558
659
|
$ teemtape share
|
|
559
660
|
$ teemtape list --json # machine-readable output for agents
|
|
560
661
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../api-client/src/client.ts","../src/index.ts","../src/output.ts","../src/commands/add.ts","../src/config.ts","../src/commands/config.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/note.ts","../src/commands/notes.ts","../src/commands/search.ts","../src/commands/share.ts","../src/context.ts","../src/net.ts"],"sourcesContent":["import type {\n CreateNoteInput,\n Note,\n NotesResponse,\n QuotesResponse,\n SymbolsListResponse,\n Watchlist,\n} from \"./types.js\";\n\nexport interface ApiClientOptions {\n /** Base URL of the Worker API, e.g. https://api.teemtape.com */\n baseUrl: string;\n /** Optional default watchlist token used by watchlist/note calls. */\n token?: string;\n /** Injectable fetch (defaults to global fetch); handy for tests. */\n fetch?: typeof fetch;\n}\n\n/** Thrown for any non-2xx API response. */\nexport class ApiError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(status: number, message: string, body: unknown) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\n/**\n * Minimal typed client for the teemtape Worker API. The same contract is reused\n * by the CLI now and the web/native apps later (see docs/cli-options.md).\n */\nexport class TeemtapeClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: ApiClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n // Wrap default fetch: assigning window.fetch to a variable breaks in browsers\n // (\"Illegal invocation\") unless called with the correct receiver.\n this.fetchImpl =\n options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n if (typeof this.fetchImpl !== \"function\") {\n throw new Error(\"No fetch implementation available (need Node 18+ or pass options.fetch).\");\n }\n }\n\n /** Delayed quotes for the given symbols. */\n async getQuotes(symbols: string[]): Promise<QuotesResponse> {\n const query = encodeURIComponent(symbols.join(\",\"));\n return this.request<QuotesResponse>(`/api/quotes?symbols=${query}`);\n }\n\n /** Paginated SEC symbol catalog with optional search and sort. */\n async listSymbols(params: {\n offset?: number;\n limit?: number;\n sort?: \"ticker\" | \"title\";\n q?: string;\n symbol?: string;\n name?: string;\n } = {}): Promise<SymbolsListResponse> {\n const search = new URLSearchParams();\n if (params.offset !== undefined) search.set(\"offset\", String(params.offset));\n if (params.limit !== undefined) search.set(\"limit\", String(params.limit));\n if (params.sort) search.set(\"sort\", params.sort);\n if (params.q) search.set(\"q\", params.q);\n if (params.symbol) search.set(\"symbol\", params.symbol);\n if (params.name) search.set(\"name\", params.name);\n const qs = search.toString();\n return this.request<SymbolsListResponse>(`/api/symbols${qs ? `?${qs}` : \"\"}`);\n }\n\n /** Create a new anonymous watchlist and return its MD5 token. */\n async createWatchlist(): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/watchlists`, { method: \"POST\" });\n }\n\n /** Fetch a watchlist (symbols + metadata) by token. */\n async getWatchlist(token = this.requireToken()): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/w/${token}`);\n }\n\n /** Add a symbol to a watchlist. */\n async addSymbol(symbol: string, token = this.requireToken()): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/w/${token}/symbols`, {\n method: \"POST\",\n body: JSON.stringify({ symbol: symbol.toUpperCase() }),\n });\n }\n\n /** Notes for a symbol on a watchlist. */\n async getNotes(symbol: string, token = this.requireToken()): Promise<NotesResponse> {\n const query = encodeURIComponent(symbol.toUpperCase());\n return this.request<NotesResponse>(`/api/w/${token}/notes?symbol=${query}`);\n }\n\n /** Post an anonymous note to a symbol. */\n async addNote(input: CreateNoteInput, token = this.requireToken()): Promise<Note> {\n return this.request<Note>(`/api/w/${token}/notes`, {\n method: \"POST\",\n body: JSON.stringify({ ...input, symbol: input.symbol.toUpperCase() }),\n });\n }\n\n private requireToken(): string {\n if (!this.token) {\n throw new Error(\"A watchlist token is required. Pass --token or set TEEMTAPE_TOKEN.\");\n }\n return this.token;\n }\n\n private async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n const headers = new Headers(init.headers);\n if (init.body && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n headers.set(\"accept\", \"application/json\");\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, { ...init, headers });\n const text = await res.text();\n const data = text ? safeJsonParse(text) : undefined;\n\n if (!res.ok) {\n const message =\n (isRecord(data) && typeof data.error === \"string\" && data.error) ||\n `Request to ${path} failed with ${res.status}`;\n throw new ApiError(res.status, message, data);\n }\n return data as T;\n }\n}\n\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","#!/usr/bin/env node\nimport { ApiError } from \"@teemtape/api-client\";\nimport { Command } from \"commander\";\nimport { addCommand } from \"./commands/add.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { noteCommand } from \"./commands/note.js\";\nimport { notesCommand } from \"./commands/notes.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { shareCommand } from \"./commands/share.js\";\nimport { createContext, type Context, type GlobalFlags } from \"./context.js\";\nimport { configureProxyFromEnv, describeNetworkError } from \"./net.js\";\nimport { c } from \"./output.js\";\n\nconfigureProxyFromEnv();\n\nconst program = new Command();\n\nprogram\n .name(\"teemtape\")\n .description(\"teemtape — list stocks and post anonymous notes from the terminal.\")\n .version(\"0.0.0\")\n .option(\"--api-url <url>\", \"Worker API base URL (env: TEEMTAPE_API_URL)\")\n .option(\"--token <token>\", \"watchlist token (env: TEEMTAPE_TOKEN)\")\n .option(\"--web-url <url>\", \"web app base URL used for share links (env: TEEMTAPE_WEB_URL)\")\n .option(\"--json\", \"output machine-readable JSON (handy for agents)\")\n .showHelpAfterError();\n\nfunction globalsOf(command: Command): GlobalFlags {\n const o = command.optsWithGlobals();\n return {\n apiUrl: o.apiUrl as string | undefined,\n token: o.token as string | undefined,\n webUrl: o.webUrl as string | undefined,\n json: Boolean(o.json),\n };\n}\n\nasync function run(command: Command, fn: (ctx: Context) => Promise<void>): Promise<void> {\n try {\n const ctx = createContext(globalsOf(command));\n await fn(ctx);\n } catch (err) {\n handleError(err);\n }\n}\n\nfunction fail(message: string): void {\n process.stderr.write(`${c.red(\"error:\")} ${message}\\n`);\n process.exitCode = 1;\n}\n\nfunction handleError(err: unknown): void {\n if (err instanceof ApiError) {\n fail(`${err.message} (HTTP ${err.status})`);\n return;\n }\n const networkMessage = describeNetworkError(err);\n if (networkMessage) {\n fail(networkMessage);\n return;\n }\n fail(err instanceof Error ? err.message : String(err));\n}\n\nprogram\n .command(\"init\")\n .description(\"create a new anonymous watchlist and save its token locally\")\n .action(async (_opts, command: Command) => run(command, (ctx) => initCommand(ctx)));\n\nprogram\n .command(\"list\")\n .description(\"show delayed quotes for your watchlist (or --symbols)\")\n .option(\"-s, --symbols <list>\", \"comma-separated symbols to show instead of the watchlist\")\n .action(async (opts: { symbols?: string }, command: Command) =>\n run(command, (ctx) => listCommand(ctx, opts)),\n );\n\nprogram\n .command(\"search\")\n .argument(\"[query]\", \"search ticker or company name (substring match)\")\n .description(\"search the SEC symbol catalog by ticker or company name\")\n .option(\"--symbol <text>\", \"filter by ticker substring only\")\n .option(\"--name <text>\", \"filter by company name substring only\")\n .option(\"--limit <n>\", \"max results to return (default 20, max 100)\")\n .option(\"--offset <n>\", \"skip first n matches (for paging)\")\n .option(\"--sort <field>\", \"sort by ticker or title\", \"ticker\")\n .action(async (query: string | undefined, opts: SearchCliOptions, command: Command) =>\n run(command, (ctx) => searchCommand(ctx, query, opts)),\n );\n\nprogram\n .command(\"add\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .description(\"add a symbol to your watchlist\")\n .action(async (symbol: string, _opts, command: Command) =>\n run(command, (ctx) => addCommand(ctx, symbol)),\n );\n\nprogram\n .command(\"notes\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .description(\"read the anonymous note thread for a symbol\")\n .action(async (symbol: string, _opts, command: Command) =>\n run(command, (ctx) => notesCommand(ctx, symbol)),\n );\n\nprogram\n .command(\"note\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .requiredOption(\"-m, --message <text>\", \"the note to post\")\n .description(\"post an anonymous note to a symbol (tagged as source: cli)\")\n .action(async (symbol: string, opts: { message?: string }, command: Command) =>\n run(command, (ctx) => noteCommand(ctx, symbol, opts)),\n );\n\nprogram\n .command(\"share\")\n .description(\"print your anonymous shareable watchlist link\")\n .action(async (_opts, command: Command) => run(command, (ctx) => shareCommand(ctx)));\n\nprogram\n .command(\"config\")\n .description(\"show the resolved configuration (token masked)\")\n .action(async (_opts, command: Command) => run(command, (ctx) => configCommand(ctx)));\n\ninterface SearchCliOptions {\n symbol?: string;\n name?: string;\n limit?: string;\n offset?: string;\n sort?: \"ticker\" | \"title\";\n}\n\nprogram.addHelpText(\n \"after\",\n `\nExamples:\n $ teemtape --api-url http://localhost:8787 init\n $ teemtape search nvidia\n $ teemtape search --symbol nv\n $ teemtape search --name microsoft\n $ teemtape add NVDA\n $ teemtape list\n $ teemtape notes NVDA\n $ teemtape note AAPL --message \"Earnings call scheduled.\"\n $ teemtape share\n $ teemtape list --json # machine-readable output for agents\n\nConfig precedence: CLI flags > env vars > ~/.config/teemtape/config.json > defaults\n`,\n);\n\nprogram.parseAsync().catch(handleError);\n","import type { Note, Quote, SymbolsListResponse } from \"@teemtape/api-client\";\n\nconst useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;\n\nconst codes = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n bold: \"\\x1b[1m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n cyan: \"\\x1b[36m\",\n} as const;\n\nfunction paint(code: string, text: string): string {\n return useColor ? `${code}${text}${codes.reset}` : text;\n}\n\nexport const c = {\n dim: (t: string) => paint(codes.dim, t),\n bold: (t: string) => paint(codes.bold, t),\n green: (t: string) => paint(codes.green, t),\n red: (t: string) => paint(codes.red, t),\n yellow: (t: string) => paint(codes.yellow, t),\n cyan: (t: string) => paint(codes.cyan, t),\n};\n\nexport function printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction money(n: number): string {\n return `$${n.toFixed(2)}`;\n}\n\nfunction signed(n: number): string {\n return `${n >= 0 ? \"+\" : \"\"}${n.toFixed(2)}`;\n}\n\nfunction pad(text: string, width: number): string {\n return text.length >= width ? text : text + \" \".repeat(width - text.length);\n}\n\nfunction padStart(text: string, width: number): string {\n return text.length >= width ? text : \" \".repeat(width - text.length) + text;\n}\n\n/** Render the watchlist quotes as an aligned table. */\nexport function printQuotesTable(quotes: Quote[], delayedSeconds: number, source: string): void {\n if (quotes.length === 0) {\n process.stdout.write(c.dim(\"No symbols on this watchlist yet. Add one with `teemtape add <SYMBOL>`.\\n\"));\n return;\n }\n\n const header = `${pad(\"SYMBOL\", 8)}${pad(\"COMPANY\", 26)}${padStart(\"LAST\", 10)} ${padStart(\"CHANGE\", 18)}`;\n process.stdout.write(`${c.dim(header)}\\n`);\n\n for (const q of quotes) {\n const changeText = `${signed(q.change)} (${signed(q.pct)}%)`;\n const colored = q.change >= 0 ? c.green(changeText) : c.red(changeText);\n const row =\n pad(q.symbol, 8) +\n pad(truncate(q.name, 25), 26) +\n padStart(money(q.price), 10) +\n \" \" +\n padStartColored(colored, changeText, 18);\n process.stdout.write(`${row}\\n`);\n }\n\n const mins = Math.round(delayedSeconds / 60);\n process.stdout.write(\n `\\n${c.dim(`# prices delayed ~${mins} min · source: ${source}`)}\\n`,\n );\n}\n\n/** Render symbol catalog search results as an aligned table. */\nexport function printSymbolsTable(res: SymbolsListResponse): void {\n if (res.symbols.length === 0) {\n process.stdout.write(c.dim(\"No symbols matched. Try a different query.\\n\"));\n return;\n }\n\n const header = `${pad(\"TICKER\", 8)}${pad(\"COMPANY\", 40)}`;\n process.stdout.write(`${c.dim(header)}\\n`);\n\n for (const s of res.symbols) {\n const row = pad(s.ticker, 8) + pad(truncate(s.title, 39), 40);\n process.stdout.write(`${row}\\n`);\n }\n\n const shown = res.symbols.length;\n const start = res.total === 0 ? 0 : res.offset + 1;\n const end = res.offset + shown;\n const range =\n res.total === 0\n ? \"0 matches\"\n : shown === 1\n ? `${start} of ${res.total}`\n : `${start}–${end} of ${res.total}`;\n process.stdout.write(`\\n${c.dim(`# ${range}`)}\\n`);\n}\n\n/** Render a note thread for a symbol. */\nexport function printNotes(symbol: string, notes: Note[]): void {\n process.stdout.write(`${c.bold(symbol)} ${c.dim(\"notes\")}\\n`);\n process.stdout.write(`${c.dim(\"─\".repeat(44))}\\n`);\n if (notes.length === 0) {\n process.stdout.write(`${c.dim(\"No notes yet. Add one with `teemtape note \" + symbol + ' --message \"…\"`.')}\\n`);\n return;\n }\n for (const n of notes) {\n const src = n.source === \"cli\" ? c.yellow(`(cli, ${rel(n.createdAt)})`) : c.dim(`(web, ${rel(n.createdAt)})`);\n process.stdout.write(`${c.cyan(n.author)} ${src}\\n`);\n process.stdout.write(` ${n.body}\\n`);\n }\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max - 1)}…`;\n}\n\n// Right-pad accounting for invisible ANSI codes by padding the plain text width.\nfunction padStartColored(colored: string, plain: string, width: number): string {\n const padding = Math.max(0, width - plain.length);\n return \" \".repeat(padding) + colored;\n}\n\nfunction rel(iso: string): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n const diffMs = Date.now() - then;\n const mins = Math.round(diffMs / 60000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n return `${Math.round(hours / 24)}d ago`;\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape add <SYMBOL>` — add a symbol to the watchlist. */\nexport async function addCommand(ctx: Context, symbol: string): Promise<void> {\n const watchlist = await ctx.client.addSymbol(symbol);\n if (ctx.json) {\n printJson(watchlist);\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Added ${c.bold(symbol.toUpperCase())}\\n`);\n process.stdout.write(` ${c.dim(`watchlist: ${watchlist.symbols.join(\", \") || \"(empty)\"}`)}\\n`);\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\n/** Resolved runtime configuration for a CLI invocation. */\nexport interface ResolvedConfig {\n apiUrl: string;\n webUrl: string;\n token?: string;\n}\n\nexport interface ConfigFlags {\n apiUrl?: string;\n webUrl?: string;\n token?: string;\n}\n\nconst DEFAULTS = {\n apiUrl: \"https://api.teemtape.com\",\n webUrl: \"https://www.teemtape.com\",\n};\n\n/** Path to the persisted config file (XDG-aware, falls back to ~/.config). */\nexport function configFilePath(): string {\n const base = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\");\n return join(base, \"teemtape\", \"config.json\");\n}\n\ninterface StoredConfig {\n apiUrl?: string;\n webUrl?: string;\n token?: string;\n}\n\nfunction readConfigFile(): StoredConfig {\n try {\n return JSON.parse(readFileSync(configFilePath(), \"utf8\")) as StoredConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Resolve config with precedence: CLI flags > environment > config file > defaults.\n * (See docs/cli-options.md.)\n */\nexport function resolveConfig(flags: ConfigFlags = {}): ResolvedConfig {\n const file = readConfigFile();\n const env = {\n apiUrl: process.env.TEEMTAPE_API_URL,\n webUrl: process.env.TEEMTAPE_WEB_URL,\n token: process.env.TEEMTAPE_TOKEN,\n };\n\n return {\n apiUrl: flags.apiUrl ?? env.apiUrl ?? file.apiUrl ?? DEFAULTS.apiUrl,\n webUrl: flags.webUrl ?? env.webUrl ?? file.webUrl ?? DEFAULTS.webUrl,\n token: flags.token ?? env.token ?? file.token,\n };\n}\n\n/** Persist values to the config file (merges with existing). */\nexport function saveConfig(patch: StoredConfig): string {\n const path = configFilePath();\n const merged = { ...readConfigFile(), ...patch };\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(merged, null, 2)}\\n`, { mode: 0o600 });\n return path;\n}\n\n/** Mask a token for display so it never gets fully printed/logged. */\nexport function maskToken(token?: string): string {\n if (!token) return \"(none)\";\n if (token.length <= 8) return \"****\";\n return `${token.slice(0, 6)}…${token.slice(-2)}`;\n}\n","import type { Context } from \"../context.js\";\nimport { configFilePath, maskToken } from \"../config.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape config` — show the resolved configuration (token masked). */\nexport async function configCommand(ctx: Context): Promise<void> {\n const view = {\n apiUrl: ctx.config.apiUrl,\n webUrl: ctx.config.webUrl,\n token: maskToken(ctx.config.token),\n configFile: configFilePath(),\n };\n if (ctx.json) {\n printJson(view);\n return;\n }\n process.stdout.write(`${c.bold(\"teemtape config\")}\\n`);\n process.stdout.write(` api url : ${view.apiUrl}\\n`);\n process.stdout.write(` web url : ${view.webUrl}\\n`);\n process.stdout.write(` token : ${view.token}\\n`);\n process.stdout.write(` ${c.dim(`config file: ${view.configFile}`)}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { saveConfig } from \"../config.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape init` — create a new anonymous watchlist and save its token locally. */\nexport async function initCommand(ctx: Context): Promise<void> {\n const watchlist = await ctx.client.createWatchlist();\n const path = saveConfig({ token: watchlist.token });\n const url = `${ctx.config.webUrl.replace(/\\/$/, \"\")}/w/${watchlist.token}`;\n\n if (ctx.json) {\n printJson({ token: watchlist.token, url, configPath: path });\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Created a new anonymous watchlist\\n`);\n process.stdout.write(` ${c.dim(`token saved to ${path}`)}\\n`);\n process.stdout.write(` ${c.dim(\"share link:\")} ${url}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { printJson, printQuotesTable } from \"../output.js\";\n\nexport interface ListOptions {\n symbols?: string;\n}\n\n/** `teemtape list` — show delayed quotes for the watchlist (or --symbols). */\nexport async function listCommand(ctx: Context, opts: ListOptions): Promise<void> {\n let symbols: string[];\n if (opts.symbols) {\n symbols = splitSymbols(opts.symbols);\n } else {\n const watchlist = await ctx.client.getWatchlist();\n symbols = watchlist.symbols;\n }\n\n if (symbols.length === 0) {\n if (ctx.json) {\n printJson({ quotes: [], delayedSeconds: 0, source: \"none\" });\n return;\n }\n process.stdout.write(\"No symbols to show. Add one with `teemtape add <SYMBOL>`.\\n\");\n return;\n }\n\n const res = await ctx.client.getQuotes(symbols);\n if (ctx.json) {\n printJson(res);\n return;\n }\n printQuotesTable(res.quotes, res.delayedSeconds, res.source);\n}\n\nfunction splitSymbols(raw: string): string[] {\n return raw\n .split(\",\")\n .map((s) => s.trim().toUpperCase())\n .filter(Boolean);\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson } from \"../output.js\";\n\nexport interface NoteOptions {\n message?: string;\n}\n\n/** `teemtape note <SYMBOL> --message \"…\"` — post an anonymous note (source: cli). */\nexport async function noteCommand(ctx: Context, symbol: string, opts: NoteOptions): Promise<void> {\n const body = opts.message?.trim();\n if (!body) {\n throw new Error(\"A note message is required. Use --message \\\"your note\\\".\");\n }\n\n const note = await ctx.client.addNote({ symbol, body, source: \"cli\" });\n if (ctx.json) {\n printJson(note);\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Note posted to ${c.bold(note.symbol)} as ${c.cyan(note.author)}\\n`);\n process.stdout.write(` ${c.dim(`id: ${note.id} · visible in web & mobile note popups`)}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { printJson, printNotes } from \"../output.js\";\n\n/** `teemtape notes <SYMBOL>` — read the note thread for a symbol. */\nexport async function notesCommand(ctx: Context, symbol: string): Promise<void> {\n const res = await ctx.client.getNotes(symbol);\n if (ctx.json) {\n printJson(res);\n return;\n }\n printNotes(res.symbol, res.notes);\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson, printSymbolsTable } from \"../output.js\";\n\nexport interface SearchOptions {\n symbol?: string;\n name?: string;\n limit?: string;\n offset?: string;\n sort?: \"ticker\" | \"title\";\n}\n\n/** `teemtape search` — find symbols in the SEC catalog by ticker or company name. */\nexport async function searchCommand(\n ctx: Context,\n query: string | undefined,\n opts: SearchOptions,\n): Promise<void> {\n const q = query?.trim();\n const symbol = opts.symbol?.trim();\n const name = opts.name?.trim();\n\n if (!q && !symbol && !name) {\n process.stderr.write(\n `${c.red(\"error:\")} provide a search query, or use --symbol and/or --name.\\n`,\n );\n process.exitCode = 1;\n return;\n }\n\n const res = await ctx.client.listSymbols({\n ...(q ? { q } : {}),\n ...(symbol ? { symbol } : {}),\n ...(name ? { name } : {}),\n ...(opts.limit !== undefined ? { limit: parsePositiveInt(opts.limit, \"limit\") } : { limit: 20 }),\n ...(opts.offset !== undefined ? { offset: parsePositiveInt(opts.offset, \"offset\") } : {}),\n ...(opts.sort ? { sort: opts.sort } : {}),\n });\n\n if (ctx.json) {\n printJson(res);\n return;\n }\n\n printSymbolsTable(res);\n}\n\nfunction parsePositiveInt(raw: string, label: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n) || n < 0) {\n throw new Error(`invalid ${label}: ${raw}`);\n }\n return n;\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape share` — print the anonymous shareable watchlist link. */\nexport async function shareCommand(ctx: Context): Promise<void> {\n const token = ctx.config.token;\n if (!token) {\n throw new Error(\"No watchlist token set. Run `teemtape init` to create one, or pass --token.\");\n }\n const url = `${ctx.config.webUrl.replace(/\\/$/, \"\")}/w/${token}`;\n if (ctx.json) {\n printJson({ url, token });\n return;\n }\n process.stdout.write(`${c.dim(\"# your anonymous watchlist link (share with anyone):\")}\\n`);\n process.stdout.write(`${url}\\n`);\n}\n","import { TeemtapeClient } from \"@teemtape/api-client\";\nimport { resolveConfig, type ConfigFlags, type ResolvedConfig } from \"./config.js\";\n\nexport interface GlobalFlags extends ConfigFlags {\n json?: boolean;\n}\n\nexport interface Context {\n config: ResolvedConfig;\n json: boolean;\n client: TeemtapeClient;\n}\n\n/** Build the per-invocation context (resolved config + a ready API client). */\nexport function createContext(flags: GlobalFlags): Context {\n const config = resolveConfig(flags);\n const client = new TeemtapeClient({ baseUrl: config.apiUrl, token: config.token });\n return { config, json: Boolean(flags.json), client };\n}\n","import { EnvHttpProxyAgent, setGlobalDispatcher } from \"undici\";\n\nconst PROXY_ENV_VARS = [\"HTTPS_PROXY\", \"https_proxy\", \"HTTP_PROXY\", \"http_proxy\"] as const;\n\n/**\n * Node's built-in `fetch` does not read the standard `HTTP(S)_PROXY` / `NO_PROXY`\n * environment variables the way tools like `curl` do. On networks that require a\n * proxy this shows up as an opaque \"fetch failed\". When a proxy variable is set,\n * route fetch through it so the CLI behaves like the rest of the user's tooling.\n */\nexport function configureProxyFromEnv(): void {\n const hasProxy = PROXY_ENV_VARS.some((name) => Boolean(process.env[name]));\n if (!hasProxy) return;\n // EnvHttpProxyAgent reads HTTP_PROXY/HTTPS_PROXY/NO_PROXY itself.\n setGlobalDispatcher(new EnvHttpProxyAgent());\n}\n\n// Node/undici error codes that mean \"the request never completed\".\nconst NETWORK_CODES = new Set([\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"EPIPE\",\n \"ENETUNREACH\",\n \"EHOSTUNREACH\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n \"UND_ERR_BODY_TIMEOUT\",\n]);\n\nconst TLS_CODES = new Set([\n \"CERT_HAS_EXPIRED\",\n \"DEPTH_ZERO_SELF_SIGNED_CERT\",\n \"SELF_SIGNED_CERT_IN_CHAIN\",\n \"UNABLE_TO_VERIFY_LEAF_SIGNATURE\",\n \"ERR_TLS_CERT_ALTNAME_INVALID\",\n]);\n\nfunction causeCode(err: Error): string | undefined {\n const cause = err.cause as { code?: unknown } | undefined;\n return typeof cause?.code === \"string\" ? cause.code : undefined;\n}\n\n/**\n * Turn the unhelpful `fetch failed` (and friends) into an actionable message that\n * names the underlying cause and points at the most common fixes. Returns\n * `undefined` for anything that is not a network/transport failure.\n */\nexport function describeNetworkError(err: unknown): string | undefined {\n if (!(err instanceof Error)) return undefined;\n const code = causeCode(err);\n const isNetworkFailure = err.message === \"fetch failed\" || (code !== undefined && NETWORK_CODES.has(code));\n if (!isNetworkFailure && !(code !== undefined && TLS_CODES.has(code))) return undefined;\n\n const reason = code ? ` (${code})` : \"\";\n const lines = [`could not reach the API${reason}.`];\n\n if (code && TLS_CODES.has(code)) {\n lines.push(\"This is a TLS/certificate problem. If a proxy or antivirus intercepts HTTPS,\");\n lines.push(\"point Node at its root certificate via NODE_EXTRA_CA_CERTS=/path/to/ca.pem.\");\n } else {\n lines.push(\"Check your connection and that the API URL is correct (run `teemtape config`).\");\n lines.push(\"Behind a proxy? Set HTTPS_PROXY (and NO_PROXY for exceptions) and retry — the CLI\");\n lines.push(\"now honors them, but Node's fetch ignores proxy settings by default (curl does not).\");\n }\n lines.push(\"For local testing run `npm run mock` and pass --api-url http://localhost:8787.\");\n return lines.join(\"\\n \");\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../api-client/src/client.ts","../src/index.ts","../src/output.ts","../src/commands/add.ts","../src/config.ts","../src/commands/config.ts","../src/handle.ts","../src/commands/handle.ts","../src/commands/init.ts","../src/commands/list.ts","../src/commands/note.ts","../src/commands/notes.ts","../src/commands/search.ts","../src/commands/share.ts","../src/context.ts","../src/net.ts"],"sourcesContent":["import type {\n CreateNoteInput,\n Handle,\n HandleAvailability,\n Note,\n NotesResponse,\n QuotesResponse,\n SymbolsListResponse,\n Watchlist,\n} from \"./types.js\";\n\nexport interface ApiClientOptions {\n /** Base URL of the Worker API, e.g. https://api.teemtape.com */\n baseUrl: string;\n /** Optional default watchlist token used by watchlist/note calls. */\n token?: string;\n /** Injectable fetch (defaults to global fetch); handy for tests. */\n fetch?: typeof fetch;\n}\n\n/** Thrown for any non-2xx API response. */\nexport class ApiError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(status: number, message: string, body: unknown) {\n super(message);\n this.name = \"ApiError\";\n this.status = status;\n this.body = body;\n }\n}\n\n/**\n * Minimal typed client for the teemtape Worker API. The same contract is reused\n * by the CLI now and the web/native apps later (see docs/cli-options.md).\n */\nexport class TeemtapeClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: ApiClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n this.token = options.token;\n // Wrap default fetch: assigning window.fetch to a variable breaks in browsers\n // (\"Illegal invocation\") unless called with the correct receiver.\n this.fetchImpl =\n options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n if (typeof this.fetchImpl !== \"function\") {\n throw new Error(\"No fetch implementation available (need Node 18+ or pass options.fetch).\");\n }\n }\n\n /** Delayed quotes for the given symbols. */\n async getQuotes(symbols: string[]): Promise<QuotesResponse> {\n const query = encodeURIComponent(symbols.join(\",\"));\n return this.request<QuotesResponse>(`/api/quotes?symbols=${query}`);\n }\n\n /** Paginated SEC symbol catalog with optional search and sort. */\n async listSymbols(params: {\n offset?: number;\n limit?: number;\n sort?: \"ticker\" | \"title\";\n q?: string;\n symbol?: string;\n name?: string;\n } = {}): Promise<SymbolsListResponse> {\n const search = new URLSearchParams();\n if (params.offset !== undefined) search.set(\"offset\", String(params.offset));\n if (params.limit !== undefined) search.set(\"limit\", String(params.limit));\n if (params.sort) search.set(\"sort\", params.sort);\n if (params.q) search.set(\"q\", params.q);\n if (params.symbol) search.set(\"symbol\", params.symbol);\n if (params.name) search.set(\"name\", params.name);\n const qs = search.toString();\n return this.request<SymbolsListResponse>(`/api/symbols${qs ? `?${qs}` : \"\"}`);\n }\n\n /** Create a new anonymous watchlist and return its MD5 token. */\n async createWatchlist(): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/watchlists`, { method: \"POST\" });\n }\n\n /**\n * Claim an anonymous handle. Pass a `handle` to request a specific one (throws\n * ApiError 409 if taken); omit it to get a fresh, unique, auto-generated one.\n */\n async createHandle(handle?: string): Promise<Handle> {\n return this.request<Handle>(`/api/handles`, {\n method: \"POST\",\n body: JSON.stringify(handle ? { handle } : {}),\n });\n }\n\n /** Check whether a specific handle is still available (not yet claimed). */\n async checkHandle(handle: string): Promise<HandleAvailability> {\n return this.request<HandleAvailability>(`/api/handles/${encodeURIComponent(handle)}`);\n }\n\n /** Fetch a watchlist (symbols + metadata) by token. */\n async getWatchlist(token = this.requireToken()): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/w/${token}`);\n }\n\n /** Add a symbol to a watchlist. */\n async addSymbol(symbol: string, token = this.requireToken()): Promise<Watchlist> {\n return this.request<Watchlist>(`/api/w/${token}/symbols`, {\n method: \"POST\",\n body: JSON.stringify({ symbol: symbol.toUpperCase() }),\n });\n }\n\n /** Notes for a symbol on a watchlist. */\n async getNotes(symbol: string, token = this.requireToken()): Promise<NotesResponse> {\n const query = encodeURIComponent(symbol.toUpperCase());\n return this.request<NotesResponse>(`/api/w/${token}/notes?symbol=${query}`);\n }\n\n /** Post an anonymous note to a symbol. */\n async addNote(input: CreateNoteInput, token = this.requireToken()): Promise<Note> {\n return this.request<Note>(`/api/w/${token}/notes`, {\n method: \"POST\",\n body: JSON.stringify({ ...input, symbol: input.symbol.toUpperCase() }),\n });\n }\n\n private requireToken(): string {\n if (!this.token) {\n throw new Error(\"A watchlist token is required. Pass --token or set TEEMTAPE_TOKEN.\");\n }\n return this.token;\n }\n\n private async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n const headers = new Headers(init.headers);\n if (init.body && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n headers.set(\"accept\", \"application/json\");\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, { ...init, headers });\n const text = await res.text();\n const data = text ? safeJsonParse(text) : undefined;\n\n if (!res.ok) {\n const message =\n (isRecord(data) && typeof data.error === \"string\" && data.error) ||\n `Request to ${path} failed with ${res.status}`;\n throw new ApiError(res.status, message, data);\n }\n return data as T;\n }\n}\n\nfunction safeJsonParse(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n","#!/usr/bin/env node\nimport { ApiError } from \"@teemtape/api-client\";\nimport { Command } from \"commander\";\nimport { addCommand } from \"./commands/add.js\";\nimport { configCommand } from \"./commands/config.js\";\nimport { handleCommand } from \"./commands/handle.js\";\nimport { initCommand } from \"./commands/init.js\";\nimport { listCommand } from \"./commands/list.js\";\nimport { noteCommand } from \"./commands/note.js\";\nimport { notesCommand } from \"./commands/notes.js\";\nimport { searchCommand } from \"./commands/search.js\";\nimport { shareCommand } from \"./commands/share.js\";\nimport { createContext, type Context, type GlobalFlags } from \"./context.js\";\nimport { configureProxyFromEnv, describeNetworkError } from \"./net.js\";\nimport { c } from \"./output.js\";\n\nconfigureProxyFromEnv();\n\nconst program = new Command();\n\nprogram\n .name(\"teemtape\")\n .description(\"teemtape — list stocks and post anonymous notes from the terminal.\")\n .version(\"0.0.0\")\n .option(\"--api-url <url>\", \"Worker API base URL (env: TEEMTAPE_API_URL)\")\n .option(\"--token <token>\", \"watchlist token (env: TEEMTAPE_TOKEN)\")\n .option(\"--handle <name>\", \"anonymous handle for posted notes (env: TEEMTAPE_HANDLE)\")\n .option(\"--web-url <url>\", \"web app base URL used for share links (env: TEEMTAPE_WEB_URL)\")\n .option(\"--json\", \"output machine-readable JSON (handy for agents)\")\n .showHelpAfterError();\n\nfunction globalsOf(command: Command): GlobalFlags {\n const o = command.optsWithGlobals();\n return {\n apiUrl: o.apiUrl as string | undefined,\n token: o.token as string | undefined,\n handle: o.handle as string | undefined,\n webUrl: o.webUrl as string | undefined,\n json: Boolean(o.json),\n };\n}\n\nasync function run(command: Command, fn: (ctx: Context) => Promise<void>): Promise<void> {\n try {\n const ctx = createContext(globalsOf(command));\n await fn(ctx);\n } catch (err) {\n handleError(err);\n }\n}\n\nfunction fail(message: string): void {\n process.stderr.write(`${c.red(\"error:\")} ${message}\\n`);\n process.exitCode = 1;\n}\n\nfunction handleError(err: unknown): void {\n if (err instanceof ApiError) {\n fail(`${err.message} (HTTP ${err.status})`);\n return;\n }\n const networkMessage = describeNetworkError(err);\n if (networkMessage) {\n fail(networkMessage);\n return;\n }\n fail(err instanceof Error ? err.message : String(err));\n}\n\nprogram\n .command(\"init\")\n .description(\"create a new anonymous watchlist and save its token locally\")\n .action(async (_opts, command: Command) => run(command, (ctx) => initCommand(ctx)));\n\nprogram\n .command(\"list\")\n .description(\"show delayed quotes for your watchlist (or --symbols)\")\n .option(\"-s, --symbols <list>\", \"comma-separated symbols to show instead of the watchlist\")\n .action(async (opts: { symbols?: string }, command: Command) =>\n run(command, (ctx) => listCommand(ctx, opts)),\n );\n\nprogram\n .command(\"search\")\n .argument(\"[query]\", \"search ticker or company name (substring match)\")\n .description(\"search the SEC symbol catalog by ticker or company name\")\n .option(\"--symbol <text>\", \"filter by ticker substring only\")\n .option(\"--name <text>\", \"filter by company name substring only\")\n .option(\"--limit <n>\", \"max results to return (default 20, max 100)\")\n .option(\"--offset <n>\", \"skip first n matches (for paging)\")\n .option(\"--sort <field>\", \"sort by ticker or title\", \"ticker\")\n .action(async (query: string | undefined, opts: SearchCliOptions, command: Command) =>\n run(command, (ctx) => searchCommand(ctx, query, opts)),\n );\n\nprogram\n .command(\"add\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .description(\"add a symbol to your watchlist\")\n .action(async (symbol: string, _opts, command: Command) =>\n run(command, (ctx) => addCommand(ctx, symbol)),\n );\n\nprogram\n .command(\"notes\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .description(\"read the anonymous note thread for a symbol\")\n .action(async (symbol: string, _opts, command: Command) =>\n run(command, (ctx) => notesCommand(ctx, symbol)),\n );\n\nprogram\n .command(\"note\")\n .argument(\"<symbol>\", \"ticker symbol, e.g. AAPL\")\n .requiredOption(\"-m, --message <text>\", \"the note to post\")\n .description(\"post an anonymous note to a symbol (tagged as source: cli)\")\n .action(async (symbol: string, opts: { message?: string }, command: Command) =>\n run(command, (ctx) => noteCommand(ctx, symbol, opts)),\n );\n\nprogram\n .command(\"share\")\n .description(\"print your anonymous shareable watchlist link\")\n .action(async (_opts, command: Command) => run(command, (ctx) => shareCommand(ctx)));\n\nprogram\n .command(\"handle\")\n .argument(\"[name]\", \"claim a specific handle, e.g. user1234\")\n .option(\"--generate\", \"generate a fresh, unique handle\")\n .description(\"show, set, or generate your anonymous handle\")\n .action(async (name: string | undefined, opts: { generate?: boolean }, command: Command) =>\n run(command, (ctx) => handleCommand(ctx, name, opts)),\n );\n\nprogram\n .command(\"config\")\n .description(\"show the resolved configuration (token masked)\")\n .action(async (_opts, command: Command) => run(command, (ctx) => configCommand(ctx)));\n\ninterface SearchCliOptions {\n symbol?: string;\n name?: string;\n limit?: string;\n offset?: string;\n sort?: \"ticker\" | \"title\";\n}\n\nprogram.addHelpText(\n \"after\",\n `\nExamples:\n $ teemtape --api-url http://localhost:8787 init\n $ teemtape search nvidia\n $ teemtape search --symbol nv\n $ teemtape search --name microsoft\n $ teemtape add NVDA\n $ teemtape list\n $ teemtape notes NVDA\n $ teemtape note AAPL --message \"Earnings call scheduled.\"\n $ teemtape handle # show your anonymous handle\n $ teemtape handle trader_jane # claim a specific handle\n $ teemtape share\n $ teemtape list --json # machine-readable output for agents\n\nConfig precedence: CLI flags > env vars > ~/.config/teemtape/config.json > defaults\n`,\n);\n\nprogram.parseAsync().catch(handleError);\n","import type { Note, Quote, SymbolsListResponse } from \"@teemtape/api-client\";\n\nconst useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;\n\nconst codes = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n bold: \"\\x1b[1m\",\n green: \"\\x1b[32m\",\n red: \"\\x1b[31m\",\n yellow: \"\\x1b[33m\",\n cyan: \"\\x1b[36m\",\n} as const;\n\nfunction paint(code: string, text: string): string {\n return useColor ? `${code}${text}${codes.reset}` : text;\n}\n\nexport const c = {\n dim: (t: string) => paint(codes.dim, t),\n bold: (t: string) => paint(codes.bold, t),\n green: (t: string) => paint(codes.green, t),\n red: (t: string) => paint(codes.red, t),\n yellow: (t: string) => paint(codes.yellow, t),\n cyan: (t: string) => paint(codes.cyan, t),\n};\n\nexport function printJson(value: unknown): void {\n process.stdout.write(`${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction money(n: number): string {\n return `$${n.toFixed(2)}`;\n}\n\nfunction signed(n: number): string {\n return `${n >= 0 ? \"+\" : \"\"}${n.toFixed(2)}`;\n}\n\nfunction pad(text: string, width: number): string {\n return text.length >= width ? text : text + \" \".repeat(width - text.length);\n}\n\nfunction padStart(text: string, width: number): string {\n return text.length >= width ? text : \" \".repeat(width - text.length) + text;\n}\n\n/** Render the watchlist quotes as an aligned table. */\nexport function printQuotesTable(quotes: Quote[], delayedSeconds: number, source: string): void {\n if (quotes.length === 0) {\n process.stdout.write(c.dim(\"No symbols on this watchlist yet. Add one with `teemtape add <SYMBOL>`.\\n\"));\n return;\n }\n\n const header = `${pad(\"SYMBOL\", 8)}${pad(\"COMPANY\", 26)}${padStart(\"LAST\", 10)} ${padStart(\"CHANGE\", 18)}`;\n process.stdout.write(`${c.dim(header)}\\n`);\n\n for (const q of quotes) {\n const changeText = `${signed(q.change)} (${signed(q.pct)}%)`;\n const colored = q.change >= 0 ? c.green(changeText) : c.red(changeText);\n const row =\n pad(q.symbol, 8) +\n pad(truncate(q.name, 25), 26) +\n padStart(money(q.price), 10) +\n \" \" +\n padStartColored(colored, changeText, 18);\n process.stdout.write(`${row}\\n`);\n }\n\n const mins = Math.round(delayedSeconds / 60);\n process.stdout.write(\n `\\n${c.dim(`# prices delayed ~${mins} min · source: ${source}`)}\\n`,\n );\n}\n\n/** Render symbol catalog search results as an aligned table. */\nexport function printSymbolsTable(res: SymbolsListResponse): void {\n if (res.symbols.length === 0) {\n process.stdout.write(c.dim(\"No symbols matched. Try a different query.\\n\"));\n return;\n }\n\n const header = `${pad(\"TICKER\", 8)}${pad(\"COMPANY\", 40)}`;\n process.stdout.write(`${c.dim(header)}\\n`);\n\n for (const s of res.symbols) {\n const row = pad(s.ticker, 8) + pad(truncate(s.title, 39), 40);\n process.stdout.write(`${row}\\n`);\n }\n\n const shown = res.symbols.length;\n const start = res.total === 0 ? 0 : res.offset + 1;\n const end = res.offset + shown;\n const range =\n res.total === 0\n ? \"0 matches\"\n : shown === 1\n ? `${start} of ${res.total}`\n : `${start}–${end} of ${res.total}`;\n process.stdout.write(`\\n${c.dim(`# ${range}`)}\\n`);\n}\n\n/** Render a note thread for a symbol. */\nexport function printNotes(symbol: string, notes: Note[]): void {\n process.stdout.write(`${c.bold(symbol)} ${c.dim(\"notes\")}\\n`);\n process.stdout.write(`${c.dim(\"─\".repeat(44))}\\n`);\n if (notes.length === 0) {\n process.stdout.write(`${c.dim(\"No notes yet. Add one with `teemtape note \" + symbol + ' --message \"…\"`.')}\\n`);\n return;\n }\n for (const n of notes) {\n const src = n.source === \"cli\" ? c.yellow(`(cli, ${rel(n.createdAt)})`) : c.dim(`(web, ${rel(n.createdAt)})`);\n process.stdout.write(`${c.cyan(n.author)} ${src}\\n`);\n process.stdout.write(` ${n.body}\\n`);\n }\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length <= max ? text : `${text.slice(0, max - 1)}…`;\n}\n\n// Right-pad accounting for invisible ANSI codes by padding the plain text width.\nfunction padStartColored(colored: string, plain: string, width: number): string {\n const padding = Math.max(0, width - plain.length);\n return \" \".repeat(padding) + colored;\n}\n\nfunction rel(iso: string): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) return iso;\n const diffMs = Date.now() - then;\n const mins = Math.round(diffMs / 60000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.round(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n return `${Math.round(hours / 24)}d ago`;\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape add <SYMBOL>` — add a symbol to the watchlist. */\nexport async function addCommand(ctx: Context, symbol: string): Promise<void> {\n const watchlist = await ctx.client.addSymbol(symbol);\n if (ctx.json) {\n printJson(watchlist);\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Added ${c.bold(symbol.toUpperCase())}\\n`);\n process.stdout.write(` ${c.dim(`watchlist: ${watchlist.symbols.join(\", \") || \"(empty)\"}`)}\\n`);\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\n/** Resolved runtime configuration for a CLI invocation. */\nexport interface ResolvedConfig {\n apiUrl: string;\n webUrl: string;\n token?: string;\n /** Anonymous handle (e.g. \"user1234\") attached to notes posted from the CLI. */\n handle?: string;\n}\n\nexport interface ConfigFlags {\n apiUrl?: string;\n webUrl?: string;\n token?: string;\n handle?: string;\n}\n\nconst DEFAULTS = {\n apiUrl: \"https://api.teemtape.com\",\n webUrl: \"https://www.teemtape.com\",\n};\n\n/** Path to the persisted config file (XDG-aware, falls back to ~/.config). */\nexport function configFilePath(): string {\n const base = process.env.XDG_CONFIG_HOME || join(homedir(), \".config\");\n return join(base, \"teemtape\", \"config.json\");\n}\n\ninterface StoredConfig {\n apiUrl?: string;\n webUrl?: string;\n token?: string;\n handle?: string;\n}\n\nfunction readConfigFile(): StoredConfig {\n try {\n return JSON.parse(readFileSync(configFilePath(), \"utf8\")) as StoredConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Resolve config with precedence: CLI flags > environment > config file > defaults.\n * (See docs/cli-options.md.)\n */\nexport function resolveConfig(flags: ConfigFlags = {}): ResolvedConfig {\n const file = readConfigFile();\n const env = {\n apiUrl: process.env.TEEMTAPE_API_URL,\n webUrl: process.env.TEEMTAPE_WEB_URL,\n token: process.env.TEEMTAPE_TOKEN,\n handle: process.env.TEEMTAPE_HANDLE,\n };\n\n return {\n apiUrl: flags.apiUrl ?? env.apiUrl ?? file.apiUrl ?? DEFAULTS.apiUrl,\n webUrl: flags.webUrl ?? env.webUrl ?? file.webUrl ?? DEFAULTS.webUrl,\n token: flags.token ?? env.token ?? file.token,\n handle: flags.handle ?? env.handle ?? file.handle,\n };\n}\n\n/** Persist values to the config file (merges with existing). */\nexport function saveConfig(patch: StoredConfig): string {\n const path = configFilePath();\n const merged = { ...readConfigFile(), ...patch };\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(merged, null, 2)}\\n`, { mode: 0o600 });\n return path;\n}\n\n/** Mask a token for display so it never gets fully printed/logged. */\nexport function maskToken(token?: string): string {\n if (!token) return \"(none)\";\n if (token.length <= 8) return \"****\";\n return `${token.slice(0, 6)}…${token.slice(-2)}`;\n}\n","import type { Context } from \"../context.js\";\nimport { configFilePath, maskToken } from \"../config.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape config` — show the resolved configuration (token masked). */\nexport async function configCommand(ctx: Context): Promise<void> {\n const view = {\n apiUrl: ctx.config.apiUrl,\n webUrl: ctx.config.webUrl,\n token: maskToken(ctx.config.token),\n handle: ctx.config.handle ?? \"(none)\",\n configFile: configFilePath(),\n };\n if (ctx.json) {\n printJson(view);\n return;\n }\n process.stdout.write(`${c.bold(\"teemtape config\")}\\n`);\n process.stdout.write(` api url : ${view.apiUrl}\\n`);\n process.stdout.write(` web url : ${view.webUrl}\\n`);\n process.stdout.write(` token : ${view.token}\\n`);\n process.stdout.write(` handle : ${view.handle}\\n`);\n process.stdout.write(` ${c.dim(`config file: ${view.configFile}`)}\\n`);\n}\n","import { saveConfig } from \"./config.js\";\nimport type { Context } from \"./context.js\";\n\n/** Allowed shape for a user-chosen anonymous handle (case-insensitive). */\nconst HANDLE_RE = /^[a-z][a-z0-9_-]{2,19}$/;\n\n/** Normalize a handle the same way the API does (trim + lowercase). */\nexport function normalizeHandle(raw: string): string {\n return raw.trim().toLowerCase();\n}\n\n/** Validate a handle locally before hitting the API, with a friendly message. */\nexport function assertValidHandle(raw: string): string {\n const handle = normalizeHandle(raw);\n if (!HANDLE_RE.test(handle)) {\n throw new Error(\n \"invalid handle: use 3-20 characters (letters, numbers, - or _) starting with a letter\",\n );\n }\n return handle;\n}\n\n/**\n * Return the configured handle, generating and persisting a unique one on first\n * use. Mirrors the web flow: a handle is auto-created and saved so notes carry a\n * stable identity, and the user can change it later with `teemtape handle`.\n */\nexport async function ensureHandle(ctx: Context): Promise<string> {\n if (ctx.config.handle) return ctx.config.handle;\n const { handle } = await ctx.client.createHandle();\n saveConfig({ handle });\n ctx.config.handle = handle;\n return handle;\n}\n\n/** Claim a specific handle and persist it. Throws on invalid/taken handles. */\nexport async function setHandle(ctx: Context, requested: string): Promise<string> {\n const wanted = assertValidHandle(requested);\n const { handle } = await ctx.client.createHandle(wanted);\n saveConfig({ handle });\n ctx.config.handle = handle;\n return handle;\n}\n\n/** Generate a fresh unique handle and persist it. */\nexport async function generateHandle(ctx: Context): Promise<string> {\n const { handle } = await ctx.client.createHandle();\n saveConfig({ handle });\n ctx.config.handle = handle;\n return handle;\n}\n","import type { Context } from \"../context.js\";\nimport { generateHandle, setHandle } from \"../handle.js\";\nimport { c, printJson } from \"../output.js\";\n\nexport interface HandleOptions {\n generate?: boolean;\n}\n\n/**\n * `teemtape handle [name]` — show, set, or generate your anonymous handle.\n *\n * teemtape handle # show the current handle\n * teemtape handle user1234 # claim a specific handle\n * teemtape handle --generate # get a fresh, unique handle\n */\nexport async function handleCommand(\n ctx: Context,\n name: string | undefined,\n opts: HandleOptions,\n): Promise<void> {\n if (name) {\n const handle = await setHandle(ctx, name);\n return report(ctx, handle, \"claimed\");\n }\n if (opts.generate) {\n const handle = await generateHandle(ctx);\n return report(ctx, handle, \"generated\");\n }\n\n const current = ctx.config.handle;\n if (ctx.json) {\n printJson({ handle: current ?? null });\n return;\n }\n if (!current) {\n process.stdout.write(\n `${c.dim(\"No handle set yet.\")} Run ${c.cyan(\"teemtape handle --generate\")} or post a note to get one.\\n`,\n );\n return;\n }\n process.stdout.write(`${c.bold(\"handle\")}: ${c.cyan(current)}\\n`);\n}\n\nfunction report(ctx: Context, handle: string, verb: string): void {\n if (ctx.json) {\n printJson({ handle });\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Handle ${verb}: ${c.cyan(handle)}\\n`);\n process.stdout.write(` ${c.dim(\"saved locally · used as the author on notes you post\")}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { saveConfig } from \"../config.js\";\nimport { ensureHandle } from \"../handle.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape init` — create a new anonymous watchlist and save its token locally. */\nexport async function initCommand(ctx: Context): Promise<void> {\n const watchlist = await ctx.client.createWatchlist();\n const path = saveConfig({ token: watchlist.token });\n ctx.config.token = watchlist.token;\n const url = `${ctx.config.webUrl.replace(/\\/$/, \"\")}/w/${watchlist.token}`;\n // Give this CLI a stable anonymous identity so its notes are attributable.\n const handle = await ensureHandle(ctx);\n\n if (ctx.json) {\n printJson({ token: watchlist.token, handle, url, configPath: path });\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Created a new anonymous watchlist\\n`);\n process.stdout.write(` ${c.dim(`token saved to ${path}`)}\\n`);\n process.stdout.write(` ${c.dim(\"handle:\")} ${c.cyan(handle)} ${c.dim(\"(change with `teemtape handle <name>`)\")}\\n`);\n process.stdout.write(` ${c.dim(\"share link:\")} ${url}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { printJson, printQuotesTable } from \"../output.js\";\n\nexport interface ListOptions {\n symbols?: string;\n}\n\n/** `teemtape list` — show delayed quotes for the watchlist (or --symbols). */\nexport async function listCommand(ctx: Context, opts: ListOptions): Promise<void> {\n let symbols: string[];\n if (opts.symbols) {\n symbols = splitSymbols(opts.symbols);\n } else {\n const watchlist = await ctx.client.getWatchlist();\n symbols = watchlist.symbols;\n }\n\n if (symbols.length === 0) {\n if (ctx.json) {\n printJson({ quotes: [], delayedSeconds: 0, source: \"none\" });\n return;\n }\n process.stdout.write(\"No symbols to show. Add one with `teemtape add <SYMBOL>`.\\n\");\n return;\n }\n\n const res = await ctx.client.getQuotes(symbols);\n if (ctx.json) {\n printJson(res);\n return;\n }\n printQuotesTable(res.quotes, res.delayedSeconds, res.source);\n}\n\nfunction splitSymbols(raw: string): string[] {\n return raw\n .split(\",\")\n .map((s) => s.trim().toUpperCase())\n .filter(Boolean);\n}\n","import type { Context } from \"../context.js\";\nimport { ensureHandle } from \"../handle.js\";\nimport { c, printJson } from \"../output.js\";\n\nexport interface NoteOptions {\n message?: string;\n}\n\n/** `teemtape note <SYMBOL> --message \"…\"` — post an anonymous note (source: cli). */\nexport async function noteCommand(ctx: Context, symbol: string, opts: NoteOptions): Promise<void> {\n const body = opts.message?.trim();\n if (!body) {\n throw new Error(\"A note message is required. Use --message \\\"your note\\\".\");\n }\n\n // First note from this CLI auto-creates and saves a unique anonymous handle.\n const handle = await ensureHandle(ctx);\n const note = await ctx.client.addNote({ symbol, body, source: \"cli\", handle });\n if (ctx.json) {\n printJson(note);\n return;\n }\n process.stdout.write(`${c.green(\"✓\")} Note posted to ${c.bold(note.symbol)} as ${c.cyan(note.author)}\\n`);\n process.stdout.write(` ${c.dim(`id: ${note.id} · visible in web & mobile note popups`)}\\n`);\n}\n","import type { Context } from \"../context.js\";\nimport { printJson, printNotes } from \"../output.js\";\n\n/** `teemtape notes <SYMBOL>` — read the note thread for a symbol. */\nexport async function notesCommand(ctx: Context, symbol: string): Promise<void> {\n const res = await ctx.client.getNotes(symbol);\n if (ctx.json) {\n printJson(res);\n return;\n }\n printNotes(res.symbol, res.notes);\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson, printSymbolsTable } from \"../output.js\";\n\nexport interface SearchOptions {\n symbol?: string;\n name?: string;\n limit?: string;\n offset?: string;\n sort?: \"ticker\" | \"title\";\n}\n\n/** `teemtape search` — find symbols in the SEC catalog by ticker or company name. */\nexport async function searchCommand(\n ctx: Context,\n query: string | undefined,\n opts: SearchOptions,\n): Promise<void> {\n const q = query?.trim();\n const symbol = opts.symbol?.trim();\n const name = opts.name?.trim();\n\n if (!q && !symbol && !name) {\n process.stderr.write(\n `${c.red(\"error:\")} provide a search query, or use --symbol and/or --name.\\n`,\n );\n process.exitCode = 1;\n return;\n }\n\n const res = await ctx.client.listSymbols({\n ...(q ? { q } : {}),\n ...(symbol ? { symbol } : {}),\n ...(name ? { name } : {}),\n ...(opts.limit !== undefined ? { limit: parsePositiveInt(opts.limit, \"limit\") } : { limit: 20 }),\n ...(opts.offset !== undefined ? { offset: parsePositiveInt(opts.offset, \"offset\") } : {}),\n ...(opts.sort ? { sort: opts.sort } : {}),\n });\n\n if (ctx.json) {\n printJson(res);\n return;\n }\n\n printSymbolsTable(res);\n}\n\nfunction parsePositiveInt(raw: string, label: string): number {\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n) || n < 0) {\n throw new Error(`invalid ${label}: ${raw}`);\n }\n return n;\n}\n","import type { Context } from \"../context.js\";\nimport { c, printJson } from \"../output.js\";\n\n/** `teemtape share` — print the anonymous shareable watchlist link. */\nexport async function shareCommand(ctx: Context): Promise<void> {\n const token = ctx.config.token;\n if (!token) {\n throw new Error(\"No watchlist token set. Run `teemtape init` to create one, or pass --token.\");\n }\n const url = `${ctx.config.webUrl.replace(/\\/$/, \"\")}/w/${token}`;\n if (ctx.json) {\n printJson({ url, token });\n return;\n }\n process.stdout.write(`${c.dim(\"# your anonymous watchlist link (share with anyone):\")}\\n`);\n process.stdout.write(`${url}\\n`);\n}\n","import { TeemtapeClient } from \"@teemtape/api-client\";\nimport { resolveConfig, type ConfigFlags, type ResolvedConfig } from \"./config.js\";\n\nexport interface GlobalFlags extends ConfigFlags {\n json?: boolean;\n}\n\nexport interface Context {\n config: ResolvedConfig;\n json: boolean;\n client: TeemtapeClient;\n}\n\n/** Build the per-invocation context (resolved config + a ready API client). */\nexport function createContext(flags: GlobalFlags): Context {\n const config = resolveConfig(flags);\n const client = new TeemtapeClient({ baseUrl: config.apiUrl, token: config.token });\n return { config, json: Boolean(flags.json), client };\n}\n","import { EnvHttpProxyAgent, setGlobalDispatcher } from \"undici\";\n\nconst PROXY_ENV_VARS = [\"HTTPS_PROXY\", \"https_proxy\", \"HTTP_PROXY\", \"http_proxy\"] as const;\n\n/**\n * Node's built-in `fetch` does not read the standard `HTTP(S)_PROXY` / `NO_PROXY`\n * environment variables the way tools like `curl` do. On networks that require a\n * proxy this shows up as an opaque \"fetch failed\". When a proxy variable is set,\n * route fetch through it so the CLI behaves like the rest of the user's tooling.\n */\nexport function configureProxyFromEnv(): void {\n const hasProxy = PROXY_ENV_VARS.some((name) => Boolean(process.env[name]));\n if (!hasProxy) return;\n // EnvHttpProxyAgent reads HTTP_PROXY/HTTPS_PROXY/NO_PROXY itself.\n setGlobalDispatcher(new EnvHttpProxyAgent());\n}\n\n// Node/undici error codes that mean \"the request never completed\".\nconst NETWORK_CODES = new Set([\n \"ENOTFOUND\",\n \"EAI_AGAIN\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"ETIMEDOUT\",\n \"EPIPE\",\n \"ENETUNREACH\",\n \"EHOSTUNREACH\",\n \"UND_ERR_CONNECT_TIMEOUT\",\n \"UND_ERR_SOCKET\",\n \"UND_ERR_HEADERS_TIMEOUT\",\n \"UND_ERR_BODY_TIMEOUT\",\n]);\n\nconst TLS_CODES = new Set([\n \"CERT_HAS_EXPIRED\",\n \"DEPTH_ZERO_SELF_SIGNED_CERT\",\n \"SELF_SIGNED_CERT_IN_CHAIN\",\n \"UNABLE_TO_VERIFY_LEAF_SIGNATURE\",\n \"ERR_TLS_CERT_ALTNAME_INVALID\",\n]);\n\nfunction causeCode(err: Error): string | undefined {\n const cause = err.cause as { code?: unknown } | undefined;\n return typeof cause?.code === \"string\" ? cause.code : undefined;\n}\n\n/**\n * Turn the unhelpful `fetch failed` (and friends) into an actionable message that\n * names the underlying cause and points at the most common fixes. Returns\n * `undefined` for anything that is not a network/transport failure.\n */\nexport function describeNetworkError(err: unknown): string | undefined {\n if (!(err instanceof Error)) return undefined;\n const code = causeCode(err);\n const isNetworkFailure = err.message === \"fetch failed\" || (code !== undefined && NETWORK_CODES.has(code));\n if (!isNetworkFailure && !(code !== undefined && TLS_CODES.has(code))) return undefined;\n\n const reason = code ? ` (${code})` : \"\";\n const lines = [`could not reach the API${reason}.`];\n\n if (code && TLS_CODES.has(code)) {\n lines.push(\"This is a TLS/certificate problem. If a proxy or antivirus intercepts HTTPS,\");\n lines.push(\"point Node at its root certificate via NODE_EXTRA_CA_CERTS=/path/to/ca.pem.\");\n } else {\n lines.push(\"Check your connection and that the API URL is correct (run `teemtape config`).\");\n lines.push(\"Behind a proxy? Set HTTPS_PROXY (and NO_PROXY for exceptions) and retry — the CLI\");\n lines.push(\"now honors them, but Node's fetch ignores proxy settings by default (curl does not).\");\n }\n lines.push(\"For local testing run `npm run mock` and pass --api-url http://localhost:8787.\");\n return lines.join(\"\\n \");\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teemtape/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "teemtape CLI — list stocks and post anonymous notes from the terminal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/kiwifellows/teemtape#readme",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"start": "node dist/index.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@teemtape/api-client": "^0.1.
|
|
30
|
+
"@teemtape/api-client": "^0.1.3",
|
|
31
31
|
"commander": "^12.1.0",
|
|
32
32
|
"undici": "^7.28.0"
|
|
33
33
|
},
|