drishti-sdk 1.0.0 → 1.0.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/README.md CHANGED
@@ -151,28 +151,7 @@ try {
151
151
 
152
152
  ## WebSocket Usage (`/v1/ws`)
153
153
 
154
- ### Async iterator style
155
-
156
- ```ts
157
- import { DrishtiClient } from "drishti-sdk";
158
-
159
- const client = new DrishtiClient({ apiKey: process.env.DRISHTI_API_KEY! });
160
- const ws = client.websocket();
161
-
162
- await ws.subscribe({ product: "announcements", symbols: ["RELIANCE"], detailed: false });
163
-
164
- for await (const event of ws.events()) {
165
- if (event.kind === "subscribed") {
166
- console.log("subscribed", event.product, event.tier);
167
- } else if (event.kind === "data") {
168
- console.log(event.channel, event.data);
169
- } else if (event.kind === "error") {
170
- console.error(event.message);
171
- }
172
- }
173
- ```
174
-
175
- ### Callback style
154
+ ### Event listeners
176
155
 
177
156
  ```ts
178
157
  import { DrishtiClient } from "drishti-sdk";
@@ -197,7 +176,28 @@ const ws = client.websocket({
197
176
  });
198
177
 
199
178
  await ws.subscribe({ product: "alerts", symbols: ["RELIANCE"] });
200
- // callbacks fire as events arrive; the session reconnects automatically
179
+ // listeners fire as events arrive; the session reconnects automatically
180
+ ```
181
+
182
+ ### Async iterator style
183
+
184
+ ```ts
185
+ import { DrishtiClient } from "drishti-sdk";
186
+
187
+ const client = new DrishtiClient({ apiKey: process.env.DRISHTI_API_KEY! });
188
+ const ws = client.websocket();
189
+
190
+ await ws.subscribe({ product: "announcements", symbols: ["RELIANCE"], detailed: false });
191
+
192
+ for await (const event of ws.events()) {
193
+ if (event.kind === "subscribed") {
194
+ console.log("subscribed", event.product, event.tier);
195
+ } else if (event.kind === "data") {
196
+ console.log(event.channel, event.data);
197
+ } else if (event.kind === "error") {
198
+ console.error(event.message);
199
+ }
200
+ }
201
201
  ```
202
202
 
203
203
  Channel-specific listeners can be registered after connect:
@@ -0,0 +1,2 @@
1
+ "use strict";var DrishtiSDK=(()=>{var v=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var Q=Object.prototype.hasOwnProperty;var H=(r,e,t)=>e in r?v(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var J=(r,e)=>{for(var t in e)v(r,t,{get:e[t],enumerable:!0})},T=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of O(e))!Q.call(r,s)&&s!==t&&v(r,s,{get:()=>e[s],enumerable:!(n=L(e,s))||n.enumerable});return r};var _=r=>T(v({},"__esModule",{value:!0}),r);var i=(r,e,t)=>H(r,typeof e!="symbol"?e+"":e,t);var K={};J(K,{DEFAULT_BASE_URL:()=>P,DRISHTI_WS_PRODUCTS:()=>g,DrishtiApiError:()=>h,DrishtiClient:()=>D,DrishtiWebSocketError:()=>d,DrishtiWebSocketSession:()=>p,buildWebSocketUrl:()=>x,parseWebSocketMessage:()=>E,serializeAnnouncementsQueryParams:()=>R,serializeQueryParams:()=>l,streamProduct:()=>I});var d=class extends Error{constructor(e){super(e),this.name="DrishtiWebSocketError"}},h=class extends Error{constructor(t,n){super(`Drishti API error ${t}: ${String(n)}`);i(this,"statusCode");i(this,"body");this.name="DrishtiApiError",this.statusCode=t,this.body=n}};var g=["news","announcements","earnings","concalls","alerts"];function W(r){let e=new Set;for(let t of r??[]){let n=String(t).trim().toUpperCase();e.add(n)}return Array.from(e)}function x(r,e){let n=r.replace(/\/+$/,"").replace(/^https:/,"wss:").replace(/^http:/,"ws:"),s=new URL(`${n}/v1/ws`);return e&&s.searchParams.set("api_key",e),s.toString()}function E(r){let e;try{e=JSON.parse(r)}catch{return{kind:"error",message:"Invalid JSON"}}if(!e||typeof e!="object"||Array.isArray(e))return{kind:"error",message:"Expected a JSON object"};let t=e;if(t.status==="subscribed"){let n=Array.isArray(t.symbols)?t.symbols.map(s=>String(s)):[];return{kind:"subscribed",product:String(t.product??""),tier:String(t.tier??""),fullFeed:!!t.full_feed,symbols:n,detailed:t.detailed!==!1}}if(t.error!==void 0)return{kind:"error",message:String(t.error),code:t.code===void 0||t.code===null?void 0:String(t.code)};if(t.channel!==void 0){let n=String(t.channel),s=t.data;return s&&typeof s=="object"&&!Array.isArray(s)?f(n)?{kind:"data",channel:n,data:s}:{kind:"data",channel:n,data:s}:f(n)?{kind:"data",channel:n,data:{raw:s}}:{kind:"data",channel:n,data:{raw:s}}}return{kind:"raw",payload:t}}function f(r){return g.includes(r)}function A(r){return JSON.stringify({op:"subscribe",product:r.product,symbols:W(r.symbols),detailed:r.detailed!==!1})}var p=class{constructor(e){i(this,"apiKey");i(this,"baseUrl");i(this,"headers");i(this,"webSocketImpl");i(this,"reconnectInitialDelayMs");i(this,"reconnectMaxDelayMs");i(this,"reconnectBackoffMultiplier");i(this,"reconnectJitterRatio");i(this,"reconnectWarnAfterAttempts");i(this,"onOpen");i(this,"onClose");i(this,"onReconnectAttempt");i(this,"onReconnectWarning");i(this,"handlers",new Map);i(this,"channelHandlers",new Map);i(this,"subscriptions",new Map);i(this,"socket",null);i(this,"queue",[]);i(this,"waiters",[]);i(this,"manuallyClosed",!1);i(this,"maintainingConnection",!1);if(!e.apiKey||e.apiKey.trim().length===0)throw new Error("DrishtiWebSocketSession requires a non-empty apiKey");this.apiKey=e.apiKey,this.baseUrl=e.baseUrl??P,this.headers={...e.headers??{}},this.webSocketImpl=e.webSocketImpl??WebSocket,this.reconnectInitialDelayMs=Math.max(100,e.reconnectInitialDelayMs??1e3),this.reconnectMaxDelayMs=Math.max(this.reconnectInitialDelayMs,e.reconnectMaxDelayMs??3e4),this.reconnectBackoffMultiplier=Math.max(1,e.reconnectBackoffMultiplier??2),this.reconnectJitterRatio=Math.min(1,Math.max(0,e.reconnectJitterRatio??.2)),this.reconnectWarnAfterAttempts=Math.max(1,e.reconnectWarnAfterAttempts??10),this.onOpen=e.onOpen,this.onClose=e.onClose,this.onReconnectAttempt=e.onReconnectAttempt,this.onReconnectWarning=e.onReconnectWarning,e.onSubscribed&&this.on("subscribed",e.onSubscribed),e.onData&&this.on("data",e.onData),e.onNews&&this.on("news",e.onNews),e.onAnnouncements&&this.on("announcements",e.onAnnouncements),e.onEarnings&&this.on("earnings",e.onEarnings),e.onConcalls&&this.on("concalls",e.onConcalls),e.onAlerts&&this.on("alerts",e.onAlerts),e.onError&&this.on("error",e.onError),e.onMessage&&this.on("message",e.onMessage),this.startConnectionMaintenance("initial")}get connected(){return this.socket!==null&&this.socket.readyState===this.webSocketImpl.OPEN}on(e,t){if(f(e)){this.addChannelListener(e,t);return}this.addEventListener(e,t)}off(e,t){if(f(e)){this.removeChannelListener(e,t);return}this.removeEventListener(e,t)}onNews(e){this.addChannelListener("news",e)}onAnnouncements(e){this.addChannelListener("announcements",e)}onEarnings(e){this.addChannelListener("earnings",e)}onConcalls(e){this.addChannelListener("concalls",e)}onAlerts(e){this.addChannelListener("alerts",e)}addEventListener(e,t){let n=this.handlers.get(e)??[];n.push(t),this.handlers.set(e,n)}removeEventListener(e,t){let s=(this.handlers.get(e)??[]).filter(a=>a!==t);if(s.length===0){this.handlers.delete(e);return}this.handlers.set(e,s)}addChannelListener(e,t){let n=this.channelHandlers.get(e)??[];n.push(t),this.channelHandlers.set(e,n)}removeChannelListener(e,t){let s=(this.channelHandlers.get(e)??[]).filter(a=>a!==t);if(s.length===0){this.channelHandlers.delete(e);return}this.channelHandlers.set(e,s)}startConnectionMaintenance(e){this.manuallyClosed||this.maintainingConnection||this.connected||this.maintainConnection(e)}async maintainConnection(e){if(this.manuallyClosed||this.maintainingConnection||this.connected)return;this.maintainingConnection=!0;let t=0,n=this.reconnectInitialDelayMs;for(;!this.manuallyClosed&&!this.connected;){t+=1,t>1&&(await this.onReconnectAttempt?.(t-1,n,e),await new Promise(s=>setTimeout(s,this.withJitter(n))));try{let s=await this.openSocket();this.socket=s,await this.resubscribeAll(),await this.onOpen?.(),t=0,n=this.reconnectInitialDelayMs;break}catch{n>=this.reconnectMaxDelayMs&&t>=this.reconnectWarnAfterAttempts&&(await this.emitReconnectWarning(t,e),t=0),n=Math.min(Math.floor(n*this.reconnectBackoffMultiplier),this.reconnectMaxDelayMs)}}this.maintainingConnection=!1}async emitReconnectWarning(e,t){if(this.onReconnectWarning){await this.onReconnectWarning(e,t);return}console.warn(`[drishti-sdk] WebSocket still unable to connect after ${e} attempts (${t}); retrying`)}async openSocket(){let e=this.createSocket();return await new Promise((t,n)=>{let s=()=>{c(),t()},a=()=>{c(),n(new d("WebSocket connection failed"))},o=u=>{c();let k="code"in u?u.code:0;n(new d(`WebSocket closed before open (code ${k})`))},c=()=>{e.removeEventListener("open",s),e.removeEventListener("error",a),e.removeEventListener("close",o)};e.addEventListener("open",s),e.addEventListener("error",a),e.addEventListener("close",o)}),this.attachSocketHandlers(e),e}attachSocketHandlers(e){e.addEventListener("message",t=>{let n=typeof t.data=="string"?t.data:String(t.data);this.handleIncoming(n)}),e.addEventListener("close",()=>{if(this.socket=null,this.onClose?.("WebSocket closed"),this.manuallyClosed){this.rejectWaiters("WebSocket closed");return}this.startConnectionMaintenance("WebSocket closed")})}createSocket(){let e=x(this.baseUrl,this.apiKey),t=this.webSocketImpl,n={...this.headers,"X-API-Key":this.apiKey};try{return new t(e,void 0,{headers:n})}catch{return new this.webSocketImpl(e)}}async close(){if(this.manuallyClosed=!0,this.maintainingConnection=!1,this.socket===null){this.rejectWaiters("WebSocket closed");return}this.socket.close(),this.socket=null,this.rejectWaiters("WebSocket closed")}async subscribe(e){let t={product:e.product,symbols:W(e.symbols),detailed:e.detailed!==!1};this.subscriptions.set(e.product,t),this.startConnectionMaintenance("subscribe"),!(!this.connected||this.socket===null)&&this.socket.send(A(t))}async dispatch(e){let t=[e.kind,"message"];for(let a of t){let o=this.handlers.get(a)??[];for(let c of o)await c(e)}if(e.kind!=="data"||!f(e.channel))return;let n=this.channelHandlers.get(e.channel)??[],s=e.data;for(let a of n)await a(s)}async handleIncoming(e){let t=E(e);await this.dispatch(t);let n=this.waiters.shift();if(n){n.resolve(t);return}this.queue.push(t)}rejectWaiters(e){let t=new d(e);for(;this.waiters.length>0;)this.waiters.shift()?.reject(t)}async resubscribeAll(){if(!(!this.connected||this.socket===null))for(let e of this.subscriptions.values())this.socket.send(A(e))}withJitter(e){if(this.reconnectJitterRatio<=0)return e;let t=Math.floor(e*this.reconnectJitterRatio),n=Math.floor(Math.random()*(t*2+1))-t;return Math.max(0,e+n)}async nextEvent(){let e=this.queue.shift();if(e)return e;if(this.manuallyClosed)throw new d("WebSocket closed");return await new Promise((t,n)=>{this.waiters.push({resolve:t,reject:n})})}async*events(){for(this.startConnectionMaintenance("events");!this.manuallyClosed;)yield await this.nextEvent()}};async function*I(r){let e=new p({apiKey:r.apiKey,baseUrl:r.baseUrl,headers:r.headers,webSocketImpl:r.webSocketImpl});try{await e.subscribe({product:r.product,symbols:r.symbols,detailed:r.detailed});for await(let t of e.events())t.kind==="data"&&(yield t.data)}finally{await e.close()}}function U(r){return r.join(",")}function l(r,e=[]){let t=new Set(e),n={};for(let[s,a]of Object.entries(r))if(a!=null){if(t.has(s)&&Array.isArray(a)){a.length>0&&(n[s]=U(a));continue}(typeof a=="string"||typeof a=="number"||typeof a=="boolean")&&(n[s]=a)}return n}function R(r){return l(r,["symbols","scrip_codes","categories"])}var P="https://developers.manasija.in";function M(r){if(!r||typeof r!="object"||Array.isArray(r))return r;let e=r;return e.earnings_table===void 0&&e.earnings_table_extraction!==void 0&&(e.earnings_table=e.earnings_table_extraction),e}function j(r,e){let t=r.replace(/\/+$/,""),n=e.replace(/^\/+/,"");return`${t}/${n}`}async function q(r){if(r.status===204)return null;let e=r.headers.get("content-type")??"",t;if(e.includes("application/json")){let n=await r.text();t=n.length>0?JSON.parse(n):null}else t=await r.text();if(!r.ok)throw new h(r.status,t);return t}var D=class{constructor(e){i(this,"baseUrl");i(this,"apiKey");i(this,"extraHeaders");i(this,"fetchImpl");i(this,"retryOptions");if(this.baseUrl=e.baseUrl??P,this.apiKey=e.apiKey,this.extraHeaders={...e.headers},this.fetchImpl=e.fetchImpl,this.retryOptions={maxRetries:e.retry?.maxRetries??2,initialDelayMs:e.retry?.initialDelayMs??300,maxDelayMs:e.retry?.maxDelayMs??5e3,multiplier:e.retry?.multiplier??2,retryOnStatuses:e.retry?.retryOnStatuses??[408,409,425,429,500,502,503,504]},!this.apiKey||this.apiKey.trim().length===0)throw new Error("DrishtiClient requires a non-empty apiKey")}resolveRetryOptions(e){return{maxRetries:e?.maxRetries??this.retryOptions.maxRetries,initialDelayMs:e?.initialDelayMs??this.retryOptions.initialDelayMs,maxDelayMs:e?.maxDelayMs??this.retryOptions.maxDelayMs,multiplier:e?.multiplier??this.retryOptions.multiplier,retryOnStatuses:e?.retryOnStatuses??this.retryOptions.retryOnStatuses}}shouldRetry(e,t,n){return t?n.includes(t.status):e instanceof TypeError}computeDelayMs(e,t){let n=t.initialDelayMs*Math.pow(t.multiplier,Math.max(0,e-1));return Math.min(t.maxDelayMs,n)}mergeHeaders(e){let t=new Headers(e);for(let[n,s]of Object.entries(this.extraHeaders))t.set(n,s);return t.set("X-API-Key",this.apiKey),t}buildPath(e,t){if(!t)return e;let n=e.replace(/:([a-zA-Z0-9_]+)/g,(s,a)=>{let o=t[a];if(o==null)throw new Error(`Missing required path param: ${a}`);return encodeURIComponent(String(o))});return n=n.replace(/\{([a-zA-Z0-9_]+)\}/g,(s,a)=>{let o=t[a];if(o==null)throw new Error(`Missing required path param: ${a}`);return encodeURIComponent(String(o))}),n}appendQuery(e,t){if(t){for(let[n,s]of Object.entries(t))if(s!=null){if(Array.isArray(s)){for(let a of s)a!=null&&e.searchParams.append(n,String(a));continue}e.searchParams.set(n,String(s))}}}async request(e,t,n={}){let s=this.buildPath(t,n.pathParams).replace(/^\/+/,""),a=new URL(j(this.baseUrl,s));this.appendQuery(a,n.query);let o=this.mergeHeaders({Accept:"application/json",...n.headers}),c=typeof FormData<"u"&&n.body instanceof FormData,u;n.body===void 0||n.body===null?u=void 0:c?u=n.body:(u=JSON.stringify(n.body),o.set("Content-Type","application/json"));let k=this.fetchImpl?this.fetchImpl.bind(globalThis):((m,y)=>globalThis.fetch(m,y)),S=this.resolveRetryOptions(n.retry),w=S.maxRetries+1,C=null;for(let m=1;m<=w;m+=1){let y=null;try{if(y=await k(a.toString(),{method:e.toUpperCase(),headers:o,body:u}),y.ok||m>=w||!this.shouldRetry(null,y,S.retryOnStatuses))return q(y)}catch(b){if(C=b,m>=w||!this.shouldRetry(b,null,S.retryOnStatuses))throw b}let B=this.computeDelayMs(m,S);await new Promise(b=>setTimeout(b,B))}throw C instanceof Error?C:new Error("Request failed after retries")}get(e,t={}){return this.request("GET",e,t)}post(e,t={}){return this.request("POST",e,t)}put(e,t={}){return this.request("PUT",e,t)}patch(e,t={}){return this.request("PATCH",e,t)}delete(e,t={}){return this.request("DELETE",e,t)}getNews(e={}){return this.get("/v1/news",{query:l(e,["symbols","scrip_codes"])})}getSymbolsMetadata(e){return this.get("/v1/symbols/metadata",{query:l(e,["symbols","scrip_codes"])})}getAnnouncementsCategories(){return this.get("/v1/announcements/categories")}getAnnouncements(e={}){return this.get("/v1/announcements",{query:R(e)})}getAnnouncementsAttachments(e){return this.get("/v1/announcements/attachments",{query:l(e,["ids"])})}postDailySummary(e){return this.post("/v1/daily-summary",{body:e.body})}getEarnings(e={}){return this.get("/v1/earnings",{query:l(e,["symbols","scrip_codes"])}).then(t=>(t.data=t.data.map(n=>M(n)),t))}getEarningsDetail(e){return this.get("/v1/earnings/detail",{query:l(e)}).then(t=>M(t))}getEarningsAttachments(e){return this.get("/v1/earnings/attachments",{query:l(e,["ids"])})}getConcalls(e={}){return this.get("/v1/concalls",{query:l(e,["symbols","scrip_codes"])})}getUpcomingConcalls(e={}){return this.get("/v1/concalls/upcoming",{query:l(e,["symbols","scrip_codes"])})}getConcallsDetail(e){return this.get("/v1/concalls/detail",{query:l(e)})}getConcallsTranscript(e){return this.get("/v1/concalls/transcript",{query:l(e)})}postConcallsTranscripts(e){return this.post("/v1/concalls/transcripts",{body:{items:e.items}})}getAlerts(e={}){return this.get("/v1/alerts",{query:l(e,["symbols","scrip_codes","type"])})}getAccount(){return this.get("/v1/account")}getAccountLimits(){return this.get("/v1/account/limits")}getAccountUsage(){return this.get("/v1/account/usage")}getAccountLedger(e={}){return this.get("/v1/account/ledger",{query:l(e)})}postBatchJobs(e){return this.postBatchJobsFile(e)}postBatchJobsFile(e){let t=new FormData;return t.append("file",e.file,e.filename??"batch.jsonl"),e.display_name!==void 0&&t.append("display_name",e.display_name),e.metadata!==void 0&&t.append("metadata",e.metadata),this.post("/v1/batch/jobs",{body:t})}getBatchJobs(e={}){return this.get("/v1/batch/jobs",{query:l(e)})}getBatchJobsJobId(e){return this.get("/v1/batch/jobs/{job_id}",{pathParams:{job_id:e.job_id}})}deleteBatchJobsJobId(e){return this.delete("/v1/batch/jobs/{job_id}",{pathParams:{job_id:e.job_id}})}getBatchJobsJobIdResults(e){return this.get("/v1/batch/jobs/{job_id}/results",{pathParams:{job_id:e.job_id}})}async waitForBatchJobCompletion(e){let t=e.pollIntervalMs??2e3,n=e.timeoutMs??300*1e3,s=new Set((e.terminalStatuses??["succeeded","partial","failed","cancelled","completed"]).map(o=>o.toLowerCase())),a=Date.now();for(;;){let o=await this.getBatchJobsJobId({job_id:e.job_id});if(s.has(o.status.toLowerCase()))return o;if(Date.now()-a>=n)throw new Error(`Timed out waiting for batch job ${e.job_id} to complete`);await new Promise(c=>setTimeout(c,t))}}async submitBatchJobAndWait(e){let t=await this.postBatchJobsFile({file:e.file,filename:e.filename,display_name:e.display_name,metadata:e.metadata});return this.waitForBatchJobCompletion({job_id:t.id,pollIntervalMs:e.pollIntervalMs,timeoutMs:e.timeoutMs,terminalStatuses:e.terminalStatuses})}websocket(e={}){return new p({apiKey:this.apiKey,baseUrl:this.baseUrl,headers:this.extraHeaders,...e})}};return _(K);})();
2
+ //# sourceMappingURL=drishti-sdk.min.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../src/errors.ts", "../src/websocket-types.ts", "../src/websocket.ts", "../src/params.ts", "../src/client.ts"],
4
+ "sourcesContent": ["export { DEFAULT_BASE_URL, DrishtiClient } from \"./client.js\";\nexport type {\n BatchWaitOptions,\n DrishtiClientOptions,\n JsonBody,\n PathParams,\n QueryParams,\n QueryValue,\n RetryOptions,\n RequestOptions,\n} from \"./client.js\";\nexport type * from \"./types.js\";\nexport type * from \"./params.js\";\nexport { serializeAnnouncementsQueryParams, serializeQueryParams } from \"./params.js\";\nexport { DrishtiApiError, DrishtiWebSocketError } from \"./errors.js\";\nexport type { ApiErrorBody } from \"./errors.js\";\nexport {\n DRISHTI_WS_PRODUCTS,\n DrishtiWebSocketSession,\n buildWebSocketUrl,\n parseWebSocketMessage,\n streamProduct,\n} from \"./websocket.js\";\nexport type {\n ChannelDataHandler,\n DrishtiWebSocketProduct,\n DrishtiWebSocketSessionOptions,\n DataEvent,\n DataPayloadByChannel,\n ErrorEvent,\n KnownDataEvent,\n RawEvent,\n SubscribeOptions,\n SubscribedEvent,\n UnknownDataEvent,\n WebSocketEvent,\n WebSocketHandler,\n} from \"./websocket.js\";\n", "export type ApiErrorBody = unknown;\n\nexport class DrishtiWebSocketError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DrishtiWebSocketError\";\n }\n}\n\nexport class DrishtiApiError extends Error {\n readonly statusCode: number;\n readonly body: ApiErrorBody;\n\n constructor(statusCode: number, body: ApiErrorBody) {\n super(`Drishti API error ${statusCode}: ${String(body)}`);\n this.name = \"DrishtiApiError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n", "import type {\n Alert,\n AnnouncementDetail,\n AnnouncementListItem,\n Concall,\n ConcallListItem,\n EarningsDetail,\n EarningsListItem,\n NewsItem,\n} from \"./types.js\";\n\nexport const DRISHTI_WS_PRODUCTS = [\n \"news\",\n \"announcements\",\n \"earnings\",\n \"concalls\",\n \"alerts\",\n] as const;\n\nexport type DrishtiWebSocketProduct = (typeof DRISHTI_WS_PRODUCTS)[number];\n\nexport type SubscribeOptions = Readonly<{\n product: DrishtiWebSocketProduct;\n symbols?: readonly string[];\n detailed?: boolean;\n}>;\n\nexport type SubscribedEvent = Readonly<{\n kind: \"subscribed\";\n product: string;\n tier: string;\n fullFeed: boolean;\n symbols: string[];\n detailed: boolean;\n}>;\n\nexport type DataPayloadByChannel = Readonly<{\n news: NewsItem;\n announcements: AnnouncementDetail | AnnouncementListItem;\n earnings: EarningsDetail | EarningsListItem;\n concalls: Concall | ConcallListItem;\n alerts: Alert;\n}>;\n\nexport type KnownDataEvent = {\n [K in DrishtiWebSocketProduct]: Readonly<{\n kind: \"data\";\n channel: K;\n data: DataPayloadByChannel[K];\n }>;\n}[DrishtiWebSocketProduct];\n\nexport type UnknownDataEvent = Readonly<{\n kind: \"data\";\n channel: string;\n data: Record<string, unknown>;\n}>;\n\nexport type DataEvent = KnownDataEvent | UnknownDataEvent;\n\nexport type ErrorEvent = Readonly<{\n kind: \"error\";\n message: string;\n code?: string;\n}>;\n\nexport type RawEvent = Readonly<{\n kind: \"raw\";\n payload: Record<string, unknown>;\n}>;\n\nexport type WebSocketEvent = SubscribedEvent | DataEvent | ErrorEvent | RawEvent;\n\nexport type WebSocketHandler = (event: WebSocketEvent) => void | Promise<void>;\n\nexport type ChannelDataHandler<K extends DrishtiWebSocketProduct> = (\n data: DataPayloadByChannel[K],\n) => void | Promise<void>;\n", "import { DEFAULT_BASE_URL } from \"./client.js\";\nimport { DrishtiWebSocketError } from \"./errors.js\";\nimport {\n DRISHTI_WS_PRODUCTS,\n} from \"./websocket-types.js\";\nimport type {\n ChannelDataHandler,\n DrishtiWebSocketProduct,\n DataPayloadByChannel,\n SubscribeOptions,\n WebSocketEvent,\n WebSocketHandler,\n} from \"./websocket-types.js\";\n\nexport {\n DRISHTI_WS_PRODUCTS,\n type DrishtiWebSocketProduct,\n type DataEvent,\n type DataPayloadByChannel,\n type ErrorEvent,\n type KnownDataEvent,\n type RawEvent,\n type SubscribeOptions,\n type SubscribedEvent,\n type UnknownDataEvent,\n type ChannelDataHandler,\n type WebSocketEvent,\n type WebSocketHandler,\n} from \"./websocket-types.js\";\n\nexport type DrishtiWebSocketSessionOptions = Readonly<{\n apiKey: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n webSocketImpl?: typeof WebSocket;\n reconnectInitialDelayMs?: number;\n reconnectMaxDelayMs?: number;\n reconnectBackoffMultiplier?: number;\n reconnectJitterRatio?: number;\n reconnectWarnAfterAttempts?: number;\n onSubscribed?: WebSocketHandler;\n onData?: WebSocketHandler;\n onNews?: ChannelDataHandler<\"news\">;\n onAnnouncements?: ChannelDataHandler<\"announcements\">;\n onEarnings?: ChannelDataHandler<\"earnings\">;\n onConcalls?: ChannelDataHandler<\"concalls\">;\n onAlerts?: ChannelDataHandler<\"alerts\">;\n onError?: WebSocketHandler;\n onMessage?: WebSocketHandler;\n onOpen?: () => void | Promise<void>;\n onClose?: (reason: string) => void | Promise<void>;\n onReconnectAttempt?: (attempt: number, delayMs: number, reason: string) => void | Promise<void>;\n onReconnectWarning?: (attempt: number, reason: string) => void | Promise<void>;\n}>;\n\nfunction normalizeSymbols(symbols: readonly string[] | undefined): string[] {\n const seen = new Set<string>();\n for (const symbol of symbols ?? []) {\n const token = String(symbol).trim().toUpperCase();\n seen.add(token);\n }\n return Array.from(seen);\n}\n\nexport function buildWebSocketUrl(baseUrl: string, apiKey?: string): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const wsBase = base.replace(/^https:/, \"wss:\").replace(/^http:/, \"ws:\");\n const url = new URL(`${wsBase}/v1/ws`);\n if (apiKey) {\n url.searchParams.set(\"api_key\", apiKey);\n }\n return url.toString();\n}\n\nexport function parseWebSocketMessage(raw: string): WebSocketEvent {\n let payload: unknown;\n try {\n payload = JSON.parse(raw) as unknown;\n } catch {\n return { kind: \"error\", message: \"Invalid JSON\" };\n }\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n return { kind: \"error\", message: \"Expected a JSON object\" };\n }\n const record = payload as Record<string, unknown>;\n if (record.status === \"subscribed\") {\n const symbols = Array.isArray(record.symbols)\n ? record.symbols.map((item) => String(item))\n : [];\n return {\n kind: \"subscribed\",\n product: String(record.product ?? \"\"),\n tier: String(record.tier ?? \"\"),\n fullFeed: Boolean(record.full_feed),\n symbols,\n detailed: record.detailed !== false,\n };\n }\n if (record.error !== undefined) {\n return {\n kind: \"error\",\n message: String(record.error),\n code: record.code === undefined || record.code === null ? undefined : String(record.code),\n };\n }\n if (record.channel !== undefined) {\n const channel = String(record.channel);\n const data = record.data;\n if (data && typeof data === \"object\" && !Array.isArray(data)) {\n if (isDrishtiWebSocketProduct(channel)) {\n return {\n kind: \"data\",\n channel,\n data: data as DataPayloadByChannel[typeof channel],\n };\n }\n return {\n kind: \"data\",\n channel,\n data: data as Record<string, unknown>,\n };\n }\n if (isDrishtiWebSocketProduct(channel)) {\n return {\n kind: \"data\",\n channel,\n data: { raw: data } as unknown as DataPayloadByChannel[typeof channel],\n };\n }\n return {\n kind: \"data\",\n channel,\n data: { raw: data },\n };\n }\n return { kind: \"raw\", payload: record };\n}\n\nfunction isDrishtiWebSocketProduct(value: string): value is DrishtiWebSocketProduct {\n return (DRISHTI_WS_PRODUCTS as readonly string[]).includes(value);\n}\n\nfunction subscribeMessage(options: SubscribeOptions): string {\n return JSON.stringify({\n op: \"subscribe\",\n product: options.product,\n symbols: normalizeSymbols(options.symbols),\n detailed: options.detailed !== false,\n });\n}\n\nexport class DrishtiWebSocketSession {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly headers: Record<string, string>;\n private readonly webSocketImpl: typeof WebSocket;\n private readonly reconnectInitialDelayMs: number;\n private readonly reconnectMaxDelayMs: number;\n private readonly reconnectBackoffMultiplier: number;\n private readonly reconnectJitterRatio: number;\n private readonly reconnectWarnAfterAttempts: number;\n private readonly onOpen?: () => void | Promise<void>;\n private readonly onClose?: (reason: string) => void | Promise<void>;\n private readonly onReconnectAttempt?: (attempt: number, delayMs: number, reason: string) => void | Promise<void>;\n private readonly onReconnectWarning?: (attempt: number, reason: string) => void | Promise<void>;\n private readonly handlers = new Map<string, WebSocketHandler[]>();\n private readonly channelHandlers = new Map<DrishtiWebSocketProduct, ChannelDataHandler<DrishtiWebSocketProduct>[]>();\n private readonly subscriptions = new Map<DrishtiWebSocketProduct, SubscribeOptions>();\n private socket: WebSocket | null = null;\n private readonly queue: WebSocketEvent[] = [];\n private readonly waiters: Array<{\n resolve: (event: WebSocketEvent) => void;\n reject: (error: Error) => void;\n }> = [];\n private manuallyClosed = false;\n private maintainingConnection = false;\n\n constructor(options: DrishtiWebSocketSessionOptions) {\n if (!options.apiKey || options.apiKey.trim().length === 0) {\n throw new Error(\"DrishtiWebSocketSession requires a non-empty apiKey\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.headers = { ...(options.headers ?? {}) };\n this.webSocketImpl = options.webSocketImpl ?? WebSocket;\n this.reconnectInitialDelayMs = Math.max(100, options.reconnectInitialDelayMs ?? 1_000);\n this.reconnectMaxDelayMs = Math.max(this.reconnectInitialDelayMs, options.reconnectMaxDelayMs ?? 30_000);\n this.reconnectBackoffMultiplier = Math.max(1, options.reconnectBackoffMultiplier ?? 2);\n this.reconnectJitterRatio = Math.min(1, Math.max(0, options.reconnectJitterRatio ?? 0.2));\n this.reconnectWarnAfterAttempts = Math.max(1, options.reconnectWarnAfterAttempts ?? 10);\n this.onOpen = options.onOpen;\n this.onClose = options.onClose;\n this.onReconnectAttempt = options.onReconnectAttempt;\n this.onReconnectWarning = options.onReconnectWarning;\n if (options.onSubscribed) {\n this.on(\"subscribed\", options.onSubscribed);\n }\n if (options.onData) {\n this.on(\"data\", options.onData);\n }\n if (options.onNews) {\n this.on(\"news\", options.onNews);\n }\n if (options.onAnnouncements) {\n this.on(\"announcements\", options.onAnnouncements);\n }\n if (options.onEarnings) {\n this.on(\"earnings\", options.onEarnings);\n }\n if (options.onConcalls) {\n this.on(\"concalls\", options.onConcalls);\n }\n if (options.onAlerts) {\n this.on(\"alerts\", options.onAlerts);\n }\n if (options.onError) {\n this.on(\"error\", options.onError);\n }\n if (options.onMessage) {\n this.on(\"message\", options.onMessage);\n }\n this.startConnectionMaintenance(\"initial\");\n }\n\n get connected(): boolean {\n return this.socket !== null && this.socket.readyState === this.webSocketImpl.OPEN;\n }\n\n on(eventName: \"data\" | \"subscribed\" | \"error\" | \"message\" | \"raw\", handler: WebSocketHandler): void;\n on<K extends DrishtiWebSocketProduct>(channel: K, handler: ChannelDataHandler<K>): void;\n on(eventName: string, handler: WebSocketHandler | ChannelDataHandler<DrishtiWebSocketProduct>): void {\n if (isDrishtiWebSocketProduct(eventName)) {\n this.addChannelListener(eventName, handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n return;\n }\n this.addEventListener(eventName, handler as WebSocketHandler);\n }\n\n off(eventName: \"data\" | \"subscribed\" | \"error\" | \"message\" | \"raw\", handler: WebSocketHandler): void;\n off<K extends DrishtiWebSocketProduct>(channel: K, handler: ChannelDataHandler<K>): void;\n off(eventName: string, handler: WebSocketHandler | ChannelDataHandler<DrishtiWebSocketProduct>): void {\n if (isDrishtiWebSocketProduct(eventName)) {\n this.removeChannelListener(eventName, handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n return;\n }\n this.removeEventListener(eventName, handler as WebSocketHandler);\n }\n\n onNews(handler: ChannelDataHandler<\"news\">): void {\n this.addChannelListener(\"news\", handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n }\n\n onAnnouncements(handler: ChannelDataHandler<\"announcements\">): void {\n this.addChannelListener(\"announcements\", handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n }\n\n onEarnings(handler: ChannelDataHandler<\"earnings\">): void {\n this.addChannelListener(\"earnings\", handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n }\n\n onConcalls(handler: ChannelDataHandler<\"concalls\">): void {\n this.addChannelListener(\"concalls\", handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n }\n\n onAlerts(handler: ChannelDataHandler<\"alerts\">): void {\n this.addChannelListener(\"alerts\", handler as ChannelDataHandler<DrishtiWebSocketProduct>);\n }\n\n private addEventListener(eventName: string, handler: WebSocketHandler): void {\n const existing = this.handlers.get(eventName) ?? [];\n existing.push(handler);\n this.handlers.set(eventName, existing);\n }\n\n private removeEventListener(eventName: string, handler: WebSocketHandler): void {\n const existing = this.handlers.get(eventName) ?? [];\n const next = existing.filter((item) => item !== handler);\n if (next.length === 0) {\n this.handlers.delete(eventName);\n return;\n }\n this.handlers.set(eventName, next);\n }\n\n private addChannelListener(\n channel: DrishtiWebSocketProduct,\n handler: ChannelDataHandler<DrishtiWebSocketProduct>,\n ): void {\n const existing = this.channelHandlers.get(channel) ?? [];\n existing.push(handler);\n this.channelHandlers.set(channel, existing);\n }\n\n private removeChannelListener(\n channel: DrishtiWebSocketProduct,\n handler: ChannelDataHandler<DrishtiWebSocketProduct>,\n ): void {\n const existing = this.channelHandlers.get(channel) ?? [];\n const next = existing.filter((item) => item !== handler);\n if (next.length === 0) {\n this.channelHandlers.delete(channel);\n return;\n }\n this.channelHandlers.set(channel, next);\n }\n\n private startConnectionMaintenance(reason: string): void {\n if (this.manuallyClosed || this.maintainingConnection || this.connected) {\n return;\n }\n void this.maintainConnection(reason);\n }\n\n private async maintainConnection(reason: string): Promise<void> {\n if (this.manuallyClosed || this.maintainingConnection || this.connected) {\n return;\n }\n this.maintainingConnection = true;\n let attempt = 0;\n let delay = this.reconnectInitialDelayMs;\n while (!this.manuallyClosed && !this.connected) {\n attempt += 1;\n if (attempt > 1) {\n await this.onReconnectAttempt?.(attempt - 1, delay, reason);\n await new Promise((resolve) => setTimeout(resolve, this.withJitter(delay)));\n }\n try {\n const socket = await this.openSocket();\n this.socket = socket;\n await this.resubscribeAll();\n await this.onOpen?.();\n attempt = 0;\n delay = this.reconnectInitialDelayMs;\n break;\n } catch {\n if (delay >= this.reconnectMaxDelayMs && attempt >= this.reconnectWarnAfterAttempts) {\n await this.emitReconnectWarning(attempt, reason);\n attempt = 0;\n }\n delay = Math.min(\n Math.floor(delay * this.reconnectBackoffMultiplier),\n this.reconnectMaxDelayMs,\n );\n }\n }\n this.maintainingConnection = false;\n }\n\n private async emitReconnectWarning(attempt: number, reason: string): Promise<void> {\n if (this.onReconnectWarning) {\n await this.onReconnectWarning(attempt, reason);\n return;\n }\n console.warn(\n `[drishti-sdk] WebSocket still unable to connect after ${attempt} attempts (${reason}); retrying`,\n );\n }\n\n private async openSocket(): Promise<WebSocket> {\n const socket = this.createSocket();\n await new Promise<void>((resolve, reject) => {\n const onOpen = (): void => {\n cleanup();\n resolve();\n };\n const onError = (): void => {\n cleanup();\n reject(new DrishtiWebSocketError(\"WebSocket connection failed\"));\n };\n const onClose = (event: CloseEvent): void => {\n cleanup();\n const code = \"code\" in event ? event.code : 0;\n reject(new DrishtiWebSocketError(`WebSocket closed before open (code ${code})`));\n };\n const cleanup = (): void => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n socket.removeEventListener(\"close\", onClose);\n };\n socket.addEventListener(\"open\", onOpen);\n socket.addEventListener(\"error\", onError);\n socket.addEventListener(\"close\", onClose);\n });\n this.attachSocketHandlers(socket);\n return socket;\n }\n\n private attachSocketHandlers(socket: WebSocket): void {\n socket.addEventListener(\"message\", (messageEvent) => {\n const raw = typeof messageEvent.data === \"string\" ? messageEvent.data : String(messageEvent.data);\n void this.handleIncoming(raw);\n });\n socket.addEventListener(\"close\", () => {\n this.socket = null;\n void this.onClose?.(\"WebSocket closed\");\n if (this.manuallyClosed) {\n this.rejectWaiters(\"WebSocket closed\");\n return;\n }\n this.startConnectionMaintenance(\"WebSocket closed\");\n });\n }\n\n private createSocket(): WebSocket {\n const url = buildWebSocketUrl(this.baseUrl, this.apiKey);\n const impl = this.webSocketImpl as unknown as {\n new (url: string, protocols?: string | string[], options?: { headers?: Record<string, string> }): WebSocket;\n };\n const headers = { ...this.headers, \"X-API-Key\": this.apiKey };\n try {\n return new impl(url, undefined, { headers });\n } catch {\n return new this.webSocketImpl(url);\n }\n }\n\n async close(): Promise<void> {\n this.manuallyClosed = true;\n this.maintainingConnection = false;\n if (this.socket === null) {\n this.rejectWaiters(\"WebSocket closed\");\n return;\n }\n this.socket.close();\n this.socket = null;\n this.rejectWaiters(\"WebSocket closed\");\n }\n\n async subscribe(options: SubscribeOptions): Promise<void> {\n const normalized: SubscribeOptions = {\n product: options.product,\n symbols: normalizeSymbols(options.symbols),\n detailed: options.detailed !== false,\n };\n this.subscriptions.set(options.product, normalized);\n this.startConnectionMaintenance(\"subscribe\");\n if (!this.connected || this.socket === null) {\n return;\n }\n this.socket.send(subscribeMessage(normalized));\n }\n\n private async dispatch(event: WebSocketEvent): Promise<void> {\n const names = [event.kind, \"message\"];\n for (const name of names) {\n const handlers = this.handlers.get(name) ?? [];\n for (const handler of handlers) {\n await handler(event);\n }\n }\n if (event.kind !== \"data\" || !isDrishtiWebSocketProduct(event.channel)) {\n return;\n }\n const channelHandlers = this.channelHandlers.get(event.channel) ?? [];\n const payload = event.data as DataPayloadByChannel[typeof event.channel];\n for (const handler of channelHandlers) {\n await handler(payload);\n }\n }\n\n private async handleIncoming(raw: string): Promise<void> {\n const event = parseWebSocketMessage(raw);\n await this.dispatch(event);\n const waiter = this.waiters.shift();\n if (waiter) {\n waiter.resolve(event);\n return;\n }\n this.queue.push(event);\n }\n\n private rejectWaiters(message: string): void {\n const error = new DrishtiWebSocketError(message);\n while (this.waiters.length > 0) {\n this.waiters.shift()?.reject(error);\n }\n }\n\n private async resubscribeAll(): Promise<void> {\n if (!this.connected || this.socket === null) {\n return;\n }\n for (const options of this.subscriptions.values()) {\n this.socket.send(subscribeMessage(options));\n }\n }\n\n private withJitter(delayMs: number): number {\n if (this.reconnectJitterRatio <= 0) {\n return delayMs;\n }\n const spread = Math.floor(delayMs * this.reconnectJitterRatio);\n const offset = Math.floor(Math.random() * (spread * 2 + 1)) - spread;\n return Math.max(0, delayMs + offset);\n }\n\n private async nextEvent(): Promise<WebSocketEvent> {\n const queued = this.queue.shift();\n if (queued) {\n return queued;\n }\n if (this.manuallyClosed) {\n throw new DrishtiWebSocketError(\"WebSocket closed\");\n }\n return await new Promise<WebSocketEvent>((resolve, reject) => {\n this.waiters.push({ resolve, reject });\n });\n }\n\n async *events(): AsyncGenerator<WebSocketEvent> {\n this.startConnectionMaintenance(\"events\");\n while (!this.manuallyClosed) {\n yield await this.nextEvent();\n }\n }\n}\n\nexport async function* streamProduct(options: {\n apiKey: string;\n product: DrishtiWebSocketProduct;\n symbols?: readonly string[];\n detailed?: boolean;\n baseUrl?: string;\n headers?: Record<string, string>;\n webSocketImpl?: typeof WebSocket;\n}): AsyncGenerator<Record<string, unknown>> {\n const session = new DrishtiWebSocketSession({\n apiKey: options.apiKey,\n baseUrl: options.baseUrl,\n headers: options.headers,\n webSocketImpl: options.webSocketImpl,\n });\n try {\n await session.subscribe({\n product: options.product,\n symbols: options.symbols,\n detailed: options.detailed,\n });\n for await (const event of session.events()) {\n if (event.kind === \"data\") {\n yield event.data;\n }\n }\n } finally {\n await session.close();\n }\n}\n", "/** Query parameter models aligned with drishti-api /v1 route definitions. */\n\nimport type { SymbolQuarterKey } from \"./types.js\";\n\nexport type NewsSentiment = \"positive\" | \"negative\" | \"neutral\";\n\n/** ISO date or datetime string (e.g. 2026-05-01 or 2026-05-11T23:59:59Z). */\nexport type IsoDateTimeParam = string;\n\n/** Fiscal quarter key accepted by detail routes (e.g. q4_26). */\nexport type FiscalQuarterParam = string;\n\nexport type NewsQueryParams = {\n /** Serialized as comma-separated `symbols`. */\n symbols?: string[];\n /** Serialized as comma-separated `scrip_codes`. */\n scrip_codes?: string[];\n sentiment?: NewsSentiment;\n /** Query key: `from`. */\n from?: IsoDateTimeParam;\n to?: IsoDateTimeParam;\n page?: number;\n limit?: number;\n};\n\nexport type PaginatedFeedQueryParams = {\n symbols?: string[];\n scrip_codes?: string[];\n from?: IsoDateTimeParam;\n to?: IsoDateTimeParam;\n detailed?: boolean;\n page?: number;\n limit?: number;\n};\n\n/** GET /v1/announcements list filter. */\nexport type AnnouncementsListQueryParams = PaginatedFeedQueryParams & {\n categories?: string[];\n important?: boolean;\n};\n\nexport type AnnouncementsQueryParams = AnnouncementsListQueryParams;\n\n/** GET /v1/earnings \u2014 same filters as announcements except categories. */\nexport type EarningsQueryParams = PaginatedFeedQueryParams;\n\nexport type ConcallsQueryParams = PaginatedFeedQueryParams;\n\nexport type UpcomingConcallsQueryParams = {\n symbols?: string[];\n scrip_codes?: string[];\n detailed?: boolean;\n page?: number;\n limit?: number;\n};\n\nexport type AlertsQueryParams = {\n symbols?: string[];\n scrip_codes?: string[];\n /** Alert type filter. Query key: `type`. */\n type?: string[];\n from?: IsoDateTimeParam;\n to?: IsoDateTimeParam;\n important?: boolean;\n page?: number;\n limit?: number;\n};\n\n/** GET /v1/announcements/attachments and GET /v1/earnings/attachments */\nexport type DocumentIdsQueryParams = {\n ids: string[];\n};\n\n/** GET /v1/symbols/metadata */\nexport type SymbolMetadataQueryParams = {\n symbols?: string[];\n scrip_codes?: string[];\n};\n\n/** Optional flags for GET /v1/earnings/detail and GET /v1/concalls/detail */\nexport type SymbolQuarterDetailQueryParams = {\n detailed?: boolean;\n};\n\n/** GET /v1/earnings/detail, GET /v1/concalls/detail, GET /v1/concalls/transcript */\nexport type SymbolQuarterQueryParams = SymbolQuarterDetailQueryParams & {\n symbol?: string;\n scrip_code?: string;\n quarter: string;\n};\n\nexport type ConcallTranscriptBatchParams = {\n items: SymbolQuarterKey[];\n};\n\nexport type BatchJobIdParams = {\n job_id: string | number;\n};\n\nexport type DailySummaryParams = {\n body: DailySummaryRequestBody;\n};\n\n/** GET /v1/account/ledger */\nexport type AccountLedgerQueryParams = {\n limit?: number;\n};\n\n/** GET /v1/batch/jobs */\nexport type BatchJobsListQueryParams = {\n limit?: number;\n};\n\nexport type DailySummaryPortfolioItem = {\n symbol: string;\n exposure: number;\n};\n\nexport type DailySummaryRequestBody = {\n portfolio: DailySummaryPortfolioItem[];\n};\n\nexport type QueryPrimitive = string | number | boolean;\n\nfunction joinList(values: string[]): string {\n return values.join(\",\");\n}\n\n/**\n * Convert a params object to flat query-string fields for HTTP.\n * Keys listed in `listKeys` are joined with commas (drishti-api list filter convention).\n */\nexport function serializeQueryParams<T extends object>(\n params: T,\n listKeys: readonly (keyof T & string)[] = []\n): Record<string, QueryPrimitive> {\n const listKeySet = new Set<string>(listKeys);\n const out: Record<string, QueryPrimitive> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value === undefined || value === null) continue;\n if (listKeySet.has(key) && Array.isArray(value)) {\n if (value.length > 0) out[key] = joinList(value);\n continue;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n out[key] = value;\n }\n }\n return out;\n}\n\n/** Announcements list vs by-id modes use different query keys. */\nexport function serializeAnnouncementsQueryParams(\n params: AnnouncementsQueryParams\n): Record<string, QueryPrimitive> {\n return serializeQueryParams(params, [\"symbols\", \"scrip_codes\", \"categories\"]);\n}\n", "import { DrishtiApiError } from \"./errors.js\";\nimport { DrishtiWebSocketSession, type DrishtiWebSocketSessionOptions } from \"./websocket.js\";\nimport {\n serializeAnnouncementsQueryParams,\n serializeQueryParams,\n type AccountLedgerQueryParams,\n type AlertsQueryParams,\n type AnnouncementsQueryParams,\n type BatchJobsListQueryParams,\n type ConcallsQueryParams,\n type UpcomingConcallsQueryParams,\n type DocumentIdsQueryParams,\n type EarningsQueryParams,\n type NewsQueryParams,\n type SymbolMetadataQueryParams,\n type SymbolQuarterQueryParams,\n type ConcallTranscriptBatchParams,\n type BatchJobIdParams,\n type DailySummaryParams,\n} from \"./params.js\";\nimport type {\n AccountDetailResponse,\n AccountLimitsResponse,\n AccountUsageEnvelope,\n Alert,\n AnnouncementDetail,\n AnnouncementListItem,\n EarningsDetail,\n EarningsListItem,\n BatchAttachmentLookupResponse,\n BatchJobCancelResponse,\n BatchJobListResponse,\n BatchJobResponse,\n Concall,\n ConcallArtifactUrlsResponse,\n ConcallTranscriptBatchResponse,\n UpcomingConcall,\n JsonValue,\n LedgerListResponse,\n NewsItem,\n PaginatedResponse,\n StringListResponse,\n SummaryResponse,\n SymbolMetadataResponse,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://developers.manasija.in\";\n\nexport type JsonBody = Record<string, JsonValue> | JsonValue[] | null;\nexport type QueryValue = string | number | boolean | null | undefined;\n/** Serialized query string map used by low-level `request()`. Prefer endpoint param types on client methods. */\nexport type QueryParams = Record<string, QueryValue | QueryValue[]>;\nexport type PathParams = Record<string, string | number>;\nexport type RequestOptions = Readonly<{\n body?: JsonBody | FormData;\n query?: QueryParams;\n pathParams?: PathParams;\n headers?: Record<string, string>;\n retry?: RetryOptions;\n}>;\n\nexport type RetryOptions = Readonly<{\n maxRetries?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n multiplier?: number;\n retryOnStatuses?: number[];\n}>;\n\nexport type DrishtiClientOptions = Readonly<{\n apiKey: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n fetchImpl?: typeof fetch;\n retry?: RetryOptions;\n}>;\n\nexport type BatchWaitOptions = Readonly<{\n pollIntervalMs?: number;\n timeoutMs?: number;\n terminalStatuses?: string[];\n}>;\n\nfunction normalizeEarningsItemPayload(item: unknown): unknown {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n return item;\n }\n const record = item as Record<string, unknown>;\n if (record.earnings_table === undefined && record.earnings_table_extraction !== undefined) {\n record.earnings_table = record.earnings_table_extraction;\n }\n return record;\n}\n\nfunction joinUrl(base: string, path: string): string {\n const b = base.replace(/\\/+$/, \"\");\n const p = path.replace(/^\\/+/, \"\");\n return `${b}/${p}`;\n}\n\nasync function parseResponse<TResponse extends JsonValue | string | null>(response: Response): Promise<TResponse> {\n if (response.status === 204) {\n return null as TResponse;\n }\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let data: JsonValue | string | null;\n if (contentType.includes(\"application/json\")) {\n const text = await response.text();\n data = text.length > 0 ? (JSON.parse(text) as JsonValue) : null;\n } else {\n data = await response.text();\n }\n if (!response.ok) {\n throw new DrishtiApiError(response.status, data);\n }\n return data as TResponse;\n}\n\nexport class DrishtiClient {\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly extraHeaders: Record<string, string>;\n private readonly fetchImpl?: typeof fetch;\n private readonly retryOptions: Required<RetryOptions>;\n\n constructor(options: DrishtiClientOptions) {\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.apiKey = options.apiKey;\n this.extraHeaders = { ...options.headers };\n this.fetchImpl = options.fetchImpl;\n this.retryOptions = {\n maxRetries: options.retry?.maxRetries ?? 2,\n initialDelayMs: options.retry?.initialDelayMs ?? 300,\n maxDelayMs: options.retry?.maxDelayMs ?? 5000,\n multiplier: options.retry?.multiplier ?? 2,\n retryOnStatuses: options.retry?.retryOnStatuses ?? [408, 409, 425, 429, 500, 502, 503, 504],\n };\n if (!this.apiKey || this.apiKey.trim().length === 0) {\n throw new Error(\"DrishtiClient requires a non-empty apiKey\");\n }\n }\n\n private resolveRetryOptions(override?: RetryOptions): Required<RetryOptions> {\n return {\n maxRetries: override?.maxRetries ?? this.retryOptions.maxRetries,\n initialDelayMs: override?.initialDelayMs ?? this.retryOptions.initialDelayMs,\n maxDelayMs: override?.maxDelayMs ?? this.retryOptions.maxDelayMs,\n multiplier: override?.multiplier ?? this.retryOptions.multiplier,\n retryOnStatuses: override?.retryOnStatuses ?? this.retryOptions.retryOnStatuses,\n };\n }\n\n private shouldRetry(error: unknown, response: Response | null, retryOnStatuses: number[]): boolean {\n if (response) {\n return retryOnStatuses.includes(response.status);\n }\n return error instanceof TypeError;\n }\n\n private computeDelayMs(attempt: number, options: Required<RetryOptions>): number {\n const exp = options.initialDelayMs * Math.pow(options.multiplier, Math.max(0, attempt - 1));\n return Math.min(options.maxDelayMs, exp);\n }\n\n private mergeHeaders(init?: HeadersInit): Headers {\n const h = new Headers(init);\n for (const [k, v] of Object.entries(this.extraHeaders)) {\n h.set(k, v);\n }\n h.set(\"X-API-Key\", this.apiKey);\n return h;\n }\n\n private buildPath(pathTemplate: string, pathParams?: PathParams): string {\n if (!pathParams) {\n return pathTemplate;\n }\n let resolved = pathTemplate.replace(/:([a-zA-Z0-9_]+)/g, (_whole: string, key: string): string => {\n const value = pathParams[key];\n if (value === undefined || value === null) {\n throw new Error(`Missing required path param: ${key}`);\n }\n return encodeURIComponent(String(value));\n });\n resolved = resolved.replace(/\\{([a-zA-Z0-9_]+)\\}/g, (_whole: string, key: string): string => {\n const value = pathParams[key];\n if (value === undefined || value === null) {\n throw new Error(`Missing required path param: ${key}`);\n }\n return encodeURIComponent(String(value));\n });\n return resolved;\n }\n\n private appendQuery(url: URL, query?: QueryParams): void {\n if (!query) {\n return;\n }\n for (const [key, rawValue] of Object.entries(query)) {\n if (rawValue === undefined || rawValue === null) {\n continue;\n }\n if (Array.isArray(rawValue)) {\n for (const value of rawValue) {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n }\n continue;\n }\n url.searchParams.set(key, String(rawValue));\n }\n }\n\n async request<TResponse extends JsonValue | string | null>(method: string, path: string, options: RequestOptions = {}): Promise<TResponse> {\n const resolvedPath = this.buildPath(path, options.pathParams).replace(/^\\/+/, \"\");\n const url = new URL(joinUrl(this.baseUrl, resolvedPath));\n this.appendQuery(url, options.query);\n const headers = this.mergeHeaders({ Accept: \"application/json\", ...options.headers });\n const isFormData = typeof FormData !== \"undefined\" && options.body instanceof FormData;\n let body: BodyInit | undefined;\n if (options.body === undefined || options.body === null) {\n body = undefined;\n } else if (isFormData) {\n body = options.body;\n } else {\n body = JSON.stringify(options.body);\n headers.set(\"Content-Type\", \"application/json\");\n }\n const fetchFn = this.fetchImpl\n ? this.fetchImpl.bind(globalThis)\n : ((input: RequestInfo | URL, init?: RequestInit) => globalThis.fetch(input, init));\n const retryOptions = this.resolveRetryOptions(options.retry);\n const maxAttempts = retryOptions.maxRetries + 1;\n let lastError: unknown = null;\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n let response: Response | null = null;\n try {\n response = await fetchFn(url.toString(), {\n method: method.toUpperCase(),\n headers,\n body,\n });\n if (response.ok || attempt >= maxAttempts || !this.shouldRetry(null, response, retryOptions.retryOnStatuses)) {\n return parseResponse<TResponse>(response);\n }\n } catch (error) {\n lastError = error;\n if (attempt >= maxAttempts || !this.shouldRetry(error, null, retryOptions.retryOnStatuses)) {\n throw error;\n }\n }\n const delayMs = this.computeDelayMs(attempt, retryOptions);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n throw lastError instanceof Error ? lastError : new Error(\"Request failed after retries\");\n }\n\n get<TResponse extends JsonValue | string | null>(path: string, options: Omit<RequestOptions, \"body\"> = {}): Promise<TResponse> {\n return this.request<TResponse>(\"GET\", path, options);\n }\n\n post<TResponse extends JsonValue | string | null>(path: string, options: RequestOptions = {}): Promise<TResponse> {\n return this.request<TResponse>(\"POST\", path, options);\n }\n\n put<TResponse extends JsonValue | string | null>(path: string, options: RequestOptions = {}): Promise<TResponse> {\n return this.request<TResponse>(\"PUT\", path, options);\n }\n\n patch<TResponse extends JsonValue | string | null>(path: string, options: RequestOptions = {}): Promise<TResponse> {\n return this.request<TResponse>(\"PATCH\", path, options);\n }\n\n delete<TResponse extends JsonValue | string | null>(path: string, options: Omit<RequestOptions, \"body\"> = {}): Promise<TResponse> {\n return this.request<TResponse>(\"DELETE\", path, options);\n }\n\n getNews(params: NewsQueryParams = {}): Promise<PaginatedResponse<NewsItem>> {\n return this.get<PaginatedResponse<NewsItem>>(\"/v1/news\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\"]),\n });\n }\n\n getSymbolsMetadata(params: SymbolMetadataQueryParams): Promise<SymbolMetadataResponse> {\n return this.get<SymbolMetadataResponse>(\"/v1/symbols/metadata\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\"]),\n });\n }\n\n getAnnouncementsCategories(): Promise<StringListResponse> {\n return this.get<StringListResponse>(\"/v1/announcements/categories\");\n }\n\n getAnnouncements(\n params: AnnouncementsQueryParams = {}\n ): Promise<PaginatedResponse<AnnouncementListItem | AnnouncementDetail>> {\n return this.get<PaginatedResponse<AnnouncementListItem | AnnouncementDetail>>(\"/v1/announcements\", {\n query: serializeAnnouncementsQueryParams(params),\n });\n }\n\n getAnnouncementsAttachments(params: DocumentIdsQueryParams): Promise<BatchAttachmentLookupResponse> {\n return this.get<BatchAttachmentLookupResponse>(\"/v1/announcements/attachments\", {\n query: serializeQueryParams(params, [\"ids\"]),\n });\n }\n\n postDailySummary(params: DailySummaryParams): Promise<SummaryResponse> {\n return this.post<SummaryResponse>(\"/v1/daily-summary\", { body: params.body });\n }\n\n getEarnings(\n params: EarningsQueryParams = {}\n ): Promise<PaginatedResponse<EarningsListItem | EarningsDetail>> {\n return this.get<PaginatedResponse<EarningsListItem | EarningsDetail>>(\"/v1/earnings\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\"]),\n }).then((response) => {\n response.data = response.data.map(\n (item) => normalizeEarningsItemPayload(item) as EarningsListItem | EarningsDetail\n );\n return response;\n });\n }\n\n getEarningsDetail(params: SymbolQuarterQueryParams): Promise<EarningsListItem | EarningsDetail> {\n return this.get<EarningsListItem | EarningsDetail>(\"/v1/earnings/detail\", {\n query: serializeQueryParams(params),\n }).then(\n (response) => normalizeEarningsItemPayload(response) as EarningsListItem | EarningsDetail\n );\n }\n\n getEarningsAttachments(params: DocumentIdsQueryParams): Promise<BatchAttachmentLookupResponse> {\n return this.get<BatchAttachmentLookupResponse>(\"/v1/earnings/attachments\", {\n query: serializeQueryParams(params, [\"ids\"]),\n });\n }\n\n getConcalls(params: ConcallsQueryParams = {}): Promise<PaginatedResponse<Concall>> {\n return this.get<PaginatedResponse<Concall>>(\"/v1/concalls\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\"]),\n });\n }\n\n getUpcomingConcalls(\n params: UpcomingConcallsQueryParams = {},\n ): Promise<PaginatedResponse<UpcomingConcall>> {\n return this.get<PaginatedResponse<UpcomingConcall>>(\"/v1/concalls/upcoming\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\"]),\n });\n }\n\n getConcallsDetail(params: SymbolQuarterQueryParams): Promise<Concall> {\n return this.get<Concall>(\"/v1/concalls/detail\", { query: serializeQueryParams(params) });\n }\n\n getConcallsTranscript(params: SymbolQuarterQueryParams): Promise<ConcallArtifactUrlsResponse> {\n return this.get<ConcallArtifactUrlsResponse>(\"/v1/concalls/transcript\", {\n query: serializeQueryParams(params),\n });\n }\n\n postConcallsTranscripts(params: ConcallTranscriptBatchParams): Promise<ConcallTranscriptBatchResponse> {\n return this.post<ConcallTranscriptBatchResponse>(\"/v1/concalls/transcripts\", { body: { items: params.items } });\n }\n\n getAlerts(params: AlertsQueryParams = {}): Promise<PaginatedResponse<Alert>> {\n return this.get<PaginatedResponse<Alert>>(\"/v1/alerts\", {\n query: serializeQueryParams(params, [\"symbols\", \"scrip_codes\", \"type\"]),\n });\n }\n\n getAccount(): Promise<AccountDetailResponse> {\n return this.get<AccountDetailResponse>(\"/v1/account\");\n }\n\n getAccountLimits(): Promise<AccountLimitsResponse> {\n return this.get<AccountLimitsResponse>(\"/v1/account/limits\");\n }\n\n getAccountUsage(): Promise<AccountUsageEnvelope> {\n return this.get<AccountUsageEnvelope>(\"/v1/account/usage\");\n }\n\n getAccountLedger(params: AccountLedgerQueryParams = {}): Promise<LedgerListResponse> {\n return this.get<LedgerListResponse>(\"/v1/account/ledger\", { query: serializeQueryParams(params) });\n }\n\n postBatchJobs(params: {\n file: Blob;\n filename?: string;\n display_name?: string;\n metadata?: string;\n }): Promise<BatchJobResponse> {\n return this.postBatchJobsFile(params);\n }\n\n postBatchJobsFile(params: {\n file: Blob;\n filename?: string;\n display_name?: string;\n metadata?: string;\n }): Promise<BatchJobResponse> {\n const form = new FormData();\n form.append(\"file\", params.file, params.filename ?? \"batch.jsonl\");\n if (params.display_name !== undefined) {\n form.append(\"display_name\", params.display_name);\n }\n if (params.metadata !== undefined) {\n form.append(\"metadata\", params.metadata);\n }\n return this.post<BatchJobResponse>(\"/v1/batch/jobs\", { body: form });\n }\n\n getBatchJobs(params: BatchJobsListQueryParams = {}): Promise<BatchJobListResponse> {\n return this.get<BatchJobListResponse>(\"/v1/batch/jobs\", { query: serializeQueryParams(params) });\n }\n\n getBatchJobsJobId(params: BatchJobIdParams): Promise<BatchJobResponse> {\n return this.get<BatchJobResponse>(\"/v1/batch/jobs/{job_id}\", { pathParams: { job_id: params.job_id } });\n }\n\n deleteBatchJobsJobId(params: BatchJobIdParams): Promise<BatchJobCancelResponse> {\n return this.delete<BatchJobCancelResponse>(\"/v1/batch/jobs/{job_id}\", { pathParams: { job_id: params.job_id } });\n }\n\n getBatchJobsJobIdResults(params: BatchJobIdParams): Promise<string> {\n return this.get<string>(\"/v1/batch/jobs/{job_id}/results\", { pathParams: { job_id: params.job_id } });\n }\n\n async waitForBatchJobCompletion(\n params: BatchJobIdParams & BatchWaitOptions\n ): Promise<BatchJobResponse> {\n const pollIntervalMs = params.pollIntervalMs ?? 2000;\n const timeoutMs = params.timeoutMs ?? 5 * 60 * 1000;\n const terminalStatuses = new Set(\n (params.terminalStatuses ?? [\"succeeded\", \"partial\", \"failed\", \"cancelled\", \"completed\"]).map((s) => s.toLowerCase())\n );\n const startedAt = Date.now();\n while (true) {\n const job = await this.getBatchJobsJobId({ job_id: params.job_id });\n if (terminalStatuses.has(job.status.toLowerCase())) {\n return job;\n }\n if (Date.now() - startedAt >= timeoutMs) {\n throw new Error(`Timed out waiting for batch job ${params.job_id} to complete`);\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n }\n\n async submitBatchJobAndWait(\n params: {\n file: Blob;\n filename?: string;\n display_name?: string;\n metadata?: string;\n } & BatchWaitOptions\n ): Promise<BatchJobResponse> {\n const job = await this.postBatchJobsFile({\n file: params.file,\n filename: params.filename,\n display_name: params.display_name,\n metadata: params.metadata,\n });\n return this.waitForBatchJobCompletion({\n job_id: job.id,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n terminalStatuses: params.terminalStatuses,\n });\n }\n\n websocket(\n options: Omit<DrishtiWebSocketSessionOptions, \"apiKey\" | \"baseUrl\" | \"headers\"> = {},\n ): DrishtiWebSocketSession {\n return new DrishtiWebSocketSession({\n apiKey: this.apiKey,\n baseUrl: this.baseUrl,\n headers: this.extraHeaders,\n ...options,\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "DEFAULT_BASE_URL", "DRISHTI_WS_PRODUCTS", "DrishtiApiError", "DrishtiClient", "DrishtiWebSocketError", "DrishtiWebSocketSession", "buildWebSocketUrl", "parseWebSocketMessage", "serializeAnnouncementsQueryParams", "serializeQueryParams", "streamProduct", "DrishtiWebSocketError", "message", "DrishtiApiError", "statusCode", "body", "__publicField", "DRISHTI_WS_PRODUCTS", "normalizeSymbols", "symbols", "seen", "symbol", "token", "buildWebSocketUrl", "baseUrl", "apiKey", "wsBase", "url", "parseWebSocketMessage", "raw", "payload", "record", "item", "channel", "data", "isDrishtiWebSocketProduct", "value", "DRISHTI_WS_PRODUCTS", "subscribeMessage", "options", "DrishtiWebSocketSession", "__publicField", "DEFAULT_BASE_URL", "eventName", "handler", "existing", "next", "reason", "attempt", "delay", "resolve", "socket", "reject", "onOpen", "cleanup", "onError", "DrishtiWebSocketError", "onClose", "event", "code", "messageEvent", "impl", "headers", "normalized", "names", "name", "handlers", "channelHandlers", "waiter", "message", "error", "delayMs", "spread", "offset", "queued", "streamProduct", "session", "joinList", "values", "serializeQueryParams", "params", "listKeys", "listKeySet", "out", "key", "value", "serializeAnnouncementsQueryParams", "DEFAULT_BASE_URL", "normalizeEarningsItemPayload", "item", "record", "joinUrl", "base", "path", "b", "p", "parseResponse", "response", "contentType", "data", "text", "DrishtiApiError", "DrishtiClient", "options", "__publicField", "override", "error", "retryOnStatuses", "attempt", "exp", "init", "h", "k", "v", "pathTemplate", "pathParams", "resolved", "_whole", "key", "value", "url", "query", "rawValue", "method", "resolvedPath", "headers", "isFormData", "body", "fetchFn", "input", "retryOptions", "maxAttempts", "lastError", "delayMs", "resolve", "params", "serializeQueryParams", "serializeAnnouncementsQueryParams", "form", "pollIntervalMs", "timeoutMs", "terminalStatuses", "s", "startedAt", "job", "DrishtiWebSocketSession"]
7
+ }
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "drishti-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "TypeScript/JavaScript client for the Drishti API (/v1)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
+ "unpkg": "dist/drishti-sdk.min.js",
9
+ "jsdelivr": "dist/drishti-sdk.min.js",
10
+ "browser": "dist/drishti-sdk.min.js",
8
11
  "sideEffects": false,
9
12
  "exports": {
10
13
  ".": {
@@ -26,7 +29,8 @@
26
29
  "LICENSE"
27
30
  ],
28
31
  "scripts": {
29
- "build": "tsc",
32
+ "build": "tsc && npm run build:browser",
33
+ "build:browser": "esbuild src/index.ts --bundle --minify --format=iife --global-name=DrishtiSDK --platform=browser --target=es2020 --sourcemap --legal-comments=none --outfile=dist/drishti-sdk.min.js",
30
34
  "prepublishOnly": "npm run build",
31
35
  "ws:listen-all": "node scripts/ws-listen-all.mjs"
32
36
  },
@@ -34,6 +38,7 @@
34
38
  "node": ">=18"
35
39
  },
36
40
  "devDependencies": {
41
+ "esbuild": "^0.28.0",
37
42
  "typescript": "~5.6.0",
38
43
  "ws": "^8.21.0"
39
44
  },