@teemtape/api-client 0.0.1 → 0.1.1

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/dist/index.d.ts CHANGED
@@ -72,7 +72,7 @@ interface SymbolsListResponse {
72
72
  }
73
73
 
74
74
  interface ApiClientOptions {
75
- /** Base URL of the Worker API, e.g. http://localhost:8787 */
75
+ /** Base URL of the Worker API, e.g. https://api.teemtape.com */
76
76
  baseUrl: string;
77
77
  /** Optional default watchlist token used by watchlist/note calls. */
78
78
  token?: string;
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ var TeemtapeClient = class {
16
16
  constructor(options) {
17
17
  this.baseUrl = options.baseUrl.replace(/\/$/, "");
18
18
  this.token = options.token;
19
- this.fetchImpl = options.fetch ?? globalThis.fetch;
19
+ this.fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
20
20
  if (typeof this.fetchImpl !== "function") {
21
21
  throw new Error("No fetch implementation available (need Node 18+ or pass options.fetch).");
22
22
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.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. http://localhost:8787 */\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 this.fetchImpl = options.fetch ?? globalThis.fetch;\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client.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"],"mappings":";AAmBO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAET,YAAY,QAAgB,SAAiB,MAAe;AAC1D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAMO,IAAM,iBAAN,MAAqB;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA2B;AACrC,SAAK,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAChD,SAAK,QAAQ,QAAQ;AAGrB,SAAK,YACH,QAAQ,UAAU,CAAC,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;AACjE,QAAI,OAAO,KAAK,cAAc,YAAY;AACxC,YAAM,IAAI,MAAM,0EAA0E;AAAA,IAC5F;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAU,SAA4C;AAC1D,UAAM,QAAQ,mBAAmB,QAAQ,KAAK,GAAG,CAAC;AAClD,WAAO,KAAK,QAAwB,uBAAuB,KAAK,EAAE;AAAA,EACpE;AAAA;AAAA,EAGA,MAAM,YAAY,SAOd,CAAC,GAAiC;AACpC,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,OAAO,WAAW,OAAW,QAAO,IAAI,UAAU,OAAO,OAAO,MAAM,CAAC;AAC3E,QAAI,OAAO,UAAU,OAAW,QAAO,IAAI,SAAS,OAAO,OAAO,KAAK,CAAC;AACxE,QAAI,OAAO,KAAM,QAAO,IAAI,QAAQ,OAAO,IAAI;AAC/C,QAAI,OAAO,EAAG,QAAO,IAAI,KAAK,OAAO,CAAC;AACtC,QAAI,OAAO,OAAQ,QAAO,IAAI,UAAU,OAAO,MAAM;AACrD,QAAI,OAAO,KAAM,QAAO,IAAI,QAAQ,OAAO,IAAI;AAC/C,UAAM,KAAK,OAAO,SAAS;AAC3B,WAAO,KAAK,QAA6B,eAAe,KAAK,IAAI,EAAE,KAAK,EAAE,EAAE;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAM,kBAAsC;AAC1C,WAAO,KAAK,QAAmB,mBAAmB,EAAE,QAAQ,OAAO,CAAC;AAAA,EACtE;AAAA;AAAA,EAGA,MAAM,aAAa,QAAQ,KAAK,aAAa,GAAuB;AAClE,WAAO,KAAK,QAAmB,UAAU,KAAK,EAAE;AAAA,EAClD;AAAA;AAAA,EAGA,MAAM,UAAU,QAAgB,QAAQ,KAAK,aAAa,GAAuB;AAC/E,WAAO,KAAK,QAAmB,UAAU,KAAK,YAAY;AAAA,MACxD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,OAAO,YAAY,EAAE,CAAC;AAAA,IACvD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAS,QAAgB,QAAQ,KAAK,aAAa,GAA2B;AAClF,UAAM,QAAQ,mBAAmB,OAAO,YAAY,CAAC;AACrD,WAAO,KAAK,QAAuB,UAAU,KAAK,iBAAiB,KAAK,EAAE;AAAA,EAC5E;AAAA;AAAA,EAGA,MAAM,QAAQ,OAAwB,QAAQ,KAAK,aAAa,GAAkB;AAChF,WAAO,KAAK,QAAc,UAAU,KAAK,UAAU;AAAA,MACjD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,GAAG,OAAO,QAAQ,MAAM,OAAO,YAAY,EAAE,CAAC;AAAA,IACvE,CAAC;AAAA,EACH;AAAA,EAEQ,eAAuB;AAC7B,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACtF;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,QAAW,MAAc,OAAoB,CAAC,GAAe;AACzE,UAAM,UAAU,IAAI,QAAQ,KAAK,OAAO;AACxC,QAAI,KAAK,QAAQ,CAAC,QAAQ,IAAI,cAAc,GAAG;AAC7C,cAAQ,IAAI,gBAAgB,kBAAkB;AAAA,IAChD;AACA,YAAQ,IAAI,UAAU,kBAAkB;AAExC,UAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC;AAC/E,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,OAAO,OAAO,cAAc,IAAI,IAAI;AAE1C,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,UACH,SAAS,IAAI,KAAK,OAAO,KAAK,UAAU,YAAY,KAAK,SAC1D,cAAc,IAAI,gBAAgB,IAAI,MAAM;AAC9C,YAAM,IAAI,SAAS,IAAI,QAAQ,SAAS,IAAI;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,MAAuB;AAC5C,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;","names":[]}
package/package.json CHANGED
@@ -1,8 +1,17 @@
1
1
  {
2
2
  "name": "@teemtape/api-client",
3
- "version": "0.0.1",
3
+ "version": "0.1.1",
4
4
  "description": "Shared typed client + types for the teemtape Worker API.",
5
5
  "license": "MIT",
6
+ "homepage": "https://github.com/kiwifellows/teemtape#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/kiwifellows/teemtape.git",
10
+ "directory": "packages/api-client"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/kiwifellows/teemtape/issues"
14
+ },
6
15
  "type": "module",
7
16
  "main": "./dist/index.js",
8
17
  "module": "./dist/index.js",