screener-india 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/lib/client/base.d.ts +16 -0
  2. package/lib/client/base.d.ts.map +1 -0
  3. package/lib/client/base.js +74 -0
  4. package/lib/client/base.js.map +1 -0
  5. package/lib/client/company.d.ts +21 -0
  6. package/lib/client/company.d.ts.map +1 -0
  7. package/lib/client/company.js +119 -0
  8. package/lib/client/company.js.map +1 -0
  9. package/lib/client/index.d.ts +22 -0
  10. package/lib/client/index.d.ts.map +1 -0
  11. package/lib/client/index.js +25 -0
  12. package/lib/client/index.js.map +1 -0
  13. package/lib/client/screens.d.ts +14 -0
  14. package/lib/client/screens.d.ts.map +1 -0
  15. package/lib/client/screens.js +88 -0
  16. package/lib/client/screens.js.map +1 -0
  17. package/lib/client/search.d.ts +10 -0
  18. package/lib/client/search.d.ts.map +1 -0
  19. package/lib/client/search.js +35 -0
  20. package/lib/client/search.js.map +1 -0
  21. package/lib/client/sectors.d.ts +15 -0
  22. package/lib/client/sectors.d.ts.map +1 -0
  23. package/lib/client/sectors.js +55 -0
  24. package/lib/client/sectors.js.map +1 -0
  25. package/lib/client.d.ts +2 -0
  26. package/lib/client.d.ts.map +1 -0
  27. package/lib/client.js +3 -0
  28. package/lib/client.js.map +1 -0
  29. package/lib/index.d.ts +3 -0
  30. package/lib/index.d.ts.map +1 -0
  31. package/lib/index.js +2 -0
  32. package/lib/index.js.map +1 -0
  33. package/lib/types.d.ts +146 -0
  34. package/lib/types.d.ts.map +1 -0
  35. package/lib/types.js +2 -0
  36. package/lib/types.js.map +1 -0
  37. package/lib/utils/cache.d.ts +10 -0
  38. package/lib/utils/cache.d.ts.map +1 -0
  39. package/lib/utils/cache.js +30 -0
  40. package/lib/utils/cache.js.map +1 -0
  41. package/lib/utils/parser.d.ts +31 -0
  42. package/lib/utils/parser.d.ts.map +1 -0
  43. package/lib/utils/parser.js +208 -0
  44. package/lib/utils/parser.js.map +1 -0
  45. package/lib/utils/retry.d.ts +2 -0
  46. package/lib/utils/retry.d.ts.map +1 -0
  47. package/lib/utils/retry.js +31 -0
  48. package/lib/utils/retry.js.map +1 -0
  49. package/lib/utils/throttle.d.ts +7 -0
  50. package/lib/utils/throttle.d.ts.map +1 -0
  51. package/lib/utils/throttle.js +20 -0
  52. package/lib/utils/throttle.js.map +1 -0
  53. package/package.json +80 -0
@@ -0,0 +1,16 @@
1
+ import { AxiosInstance } from "axios";
2
+ import type { ClientConfig, CompanyMode, Meta } from "../types.js";
3
+ import { TtlCache } from "../utils/cache.js";
4
+ import { Throttle } from "../utils/throttle.js";
5
+ export declare abstract class BaseClient {
6
+ protected readonly http: AxiosInstance;
7
+ protected readonly cache: TtlCache;
8
+ protected readonly throttle: Throttle;
9
+ protected readonly config: Required<ClientConfig>;
10
+ constructor(config?: ClientConfig);
11
+ protected cacheKey(url: string): string;
12
+ protected meta(url: string): Meta;
13
+ protected fetchHtml(url: string, scope?: string): Promise<string>;
14
+ protected companyUrl(symbol: string, mode: CompanyMode): string;
15
+ }
16
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/client/base.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOhD,8BAAsB,UAAU;IAC9B,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACnC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IACtC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;gBAEtC,MAAM,GAAE,YAAiB;IA8BrC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIvC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;cAQjB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB1E,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM;CAIhE"}
@@ -0,0 +1,74 @@
1
+ import axios from "axios";
2
+ import crypto from "crypto";
3
+ import { TtlCache } from "../utils/cache.js";
4
+ import { Throttle } from "../utils/throttle.js";
5
+ import { retryWithBackoff } from "../utils/retry.js";
6
+ const PARSER_VERSION = "1.0.0";
7
+ const DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
8
+ export class BaseClient {
9
+ http;
10
+ cache;
11
+ throttle;
12
+ config;
13
+ constructor(config = {}) {
14
+ this.config = {
15
+ baseUrl: config.baseUrl ?? "https://www.screener.in",
16
+ cacheTtlMs: config.cacheTtlMs ?? 300_000,
17
+ minIntervalMs: config.minIntervalMs ?? 200,
18
+ maxRetries: config.maxRetries ?? 2,
19
+ timeoutMs: config.timeoutMs ?? 20_000,
20
+ proxyUrl: config.proxyUrl ?? "",
21
+ cookies: config.cookies ?? "",
22
+ };
23
+ const defaultHeaders = {
24
+ "User-Agent": DEFAULT_USER_AGENT,
25
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
26
+ "Accept-Language": "en-US,en;q=0.9",
27
+ };
28
+ if (this.config.cookies) {
29
+ defaultHeaders["Cookie"] = this.config.cookies;
30
+ }
31
+ this.http = axios.create({
32
+ timeout: this.config.timeoutMs,
33
+ headers: defaultHeaders,
34
+ });
35
+ this.cache = new TtlCache(this.config.cacheTtlMs);
36
+ this.throttle = new Throttle(this.config.minIntervalMs);
37
+ }
38
+ cacheKey(url) {
39
+ return crypto.createHash("sha256").update(url).digest("hex");
40
+ }
41
+ meta(url) {
42
+ return {
43
+ sourceUrl: url,
44
+ fetchedAt: new Date().toISOString(),
45
+ parserVersion: PARSER_VERSION,
46
+ };
47
+ }
48
+ async fetchHtml(url, scope = "default") {
49
+ const key = this.cacheKey(url);
50
+ const cached = this.cache.get(key);
51
+ if (cached)
52
+ return cached;
53
+ await this.throttle.wait(scope);
54
+ const html = await retryWithBackoff(async () => {
55
+ const res = await this.http.get(url, {
56
+ responseType: "text",
57
+ maxRedirects: 5,
58
+ });
59
+ // Detect login-wall: screener.in redirects protected pages to /register/ or /login/
60
+ const finalUrl = res.request?.res?.responseUrl ?? "";
61
+ if (finalUrl.includes("/register") || finalUrl.includes("/login")) {
62
+ throw new Error(`LOGIN_REQUIRED: ${url} requires a screener.in account`);
63
+ }
64
+ return res.data;
65
+ }, this.config.maxRetries);
66
+ this.cache.set(key, html);
67
+ return html;
68
+ }
69
+ companyUrl(symbol, mode) {
70
+ const base = `${this.config.baseUrl}/company/${symbol.toUpperCase()}`;
71
+ return mode === "consolidated" ? `${base}/consolidated/` : `${base}/`;
72
+ }
73
+ }
74
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/client/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { CompanyMode, CompanyTab, CompanyData, CompanyRaw, CompanySummary, ApiResponse } from "../types.js";
2
+ import { BaseClient } from "./base.js";
3
+ export declare abstract class CompanyClient extends BaseClient {
4
+ /**
5
+ * Fetch full company snapshot — ratios, financials, analysis, peers, documents.
6
+ */
7
+ getCompany(symbol: string, mode?: CompanyMode): Promise<ApiResponse<CompanyData>>;
8
+ /**
9
+ * Fetch a specific financial tab for a company.
10
+ */
11
+ getCompanyTab(symbol: string, tab: CompanyTab, mode?: CompanyMode): Promise<ApiResponse<Partial<CompanyData>>>;
12
+ /**
13
+ * Fetch raw HTML and available section IDs for a company page.
14
+ */
15
+ getCompanyRaw(symbol: string, mode?: CompanyMode): Promise<ApiResponse<CompanyRaw>>;
16
+ /**
17
+ * Compare multiple companies side-by-side — returns a summary row per symbol.
18
+ */
19
+ compareCompanies(symbols: string[], mode?: CompanyMode): Promise<ApiResponse<CompanySummary[]>>;
20
+ }
21
+ //# sourceMappingURL=company.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"company.d.ts","sourceRoot":"","sources":["../../src/client/company.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,WAAW,EACZ,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,8BAAsB,aAAc,SAAQ,UAAU;IACpD;;OAEG;IACG,UAAU,CACd,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,WAA4B,GACjC,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IA2BpC;;OAEG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,IAAI,GAAE,WAA4B,GACjC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IA4C7C;;OAEG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,WAA4B,GACjC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAYnC;;OAEG;IACG,gBAAgB,CACpB,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,GAAE,WAA4B,GACjC,OAAO,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC,CAAC;CAiC1C"}
@@ -0,0 +1,119 @@
1
+ import { parseHtml, parseTitle, parseTopRatios, parseTable, parseAnalysis, parseDocuments, parsePeers, parseSectionIds, } from "../utils/parser.js";
2
+ import { BaseClient } from "./base.js";
3
+ export class CompanyClient extends BaseClient {
4
+ /**
5
+ * Fetch full company snapshot — ratios, financials, analysis, peers, documents.
6
+ */
7
+ async getCompany(symbol, mode = "consolidated") {
8
+ const url = this.companyUrl(symbol, mode);
9
+ const html = await this.fetchHtml(url, "company");
10
+ const root = parseHtml(html);
11
+ const warnings = [];
12
+ const data = {
13
+ name: parseTitle(root),
14
+ symbol: symbol.toUpperCase(),
15
+ mode,
16
+ topRatios: parseTopRatios(root),
17
+ quarters: parseTable(root.querySelector("section#quarters")),
18
+ profitLoss: parseTable(root.querySelector("section#profit-loss")),
19
+ balanceSheet: parseTable(root.querySelector("section#balance-sheet")),
20
+ cashFlow: parseTable(root.querySelector("section#cash-flow")),
21
+ ratios: parseTable(root.querySelector("section#ratios")),
22
+ shareholding: parseTable(root.querySelector("section#shareholding")),
23
+ documents: parseDocuments(root),
24
+ analysis: parseAnalysis(root),
25
+ peers: parsePeers(root),
26
+ };
27
+ if (!data.name)
28
+ warnings.push("Could not parse company name");
29
+ return { data, meta: this.meta(url), warnings };
30
+ }
31
+ /**
32
+ * Fetch a specific financial tab for a company.
33
+ */
34
+ async getCompanyTab(symbol, tab, mode = "consolidated") {
35
+ const url = this.companyUrl(symbol, mode);
36
+ const html = await this.fetchHtml(url, "company");
37
+ const root = parseHtml(html);
38
+ const warnings = [];
39
+ const tabData = {
40
+ symbol: symbol.toUpperCase(),
41
+ mode,
42
+ };
43
+ switch (tab) {
44
+ case "quarters":
45
+ tabData.quarters = parseTable(root.querySelector("section#quarters"));
46
+ break;
47
+ case "profit-loss":
48
+ tabData.profitLoss = parseTable(root.querySelector("section#profit-loss"));
49
+ break;
50
+ case "balance-sheet":
51
+ tabData.balanceSheet = parseTable(root.querySelector("section#balance-sheet"));
52
+ break;
53
+ case "cash-flow":
54
+ tabData.cashFlow = parseTable(root.querySelector("section#cash-flow"));
55
+ break;
56
+ case "ratios":
57
+ tabData.ratios = parseTable(root.querySelector("section#ratios"));
58
+ break;
59
+ case "shareholding":
60
+ tabData.shareholding = parseTable(root.querySelector("section#shareholding"));
61
+ break;
62
+ case "documents":
63
+ tabData.documents = parseDocuments(root);
64
+ break;
65
+ case "analysis":
66
+ tabData.analysis = parseAnalysis(root);
67
+ break;
68
+ case "peers":
69
+ tabData.peers = parsePeers(root);
70
+ break;
71
+ }
72
+ return { data: tabData, meta: this.meta(url), warnings };
73
+ }
74
+ /**
75
+ * Fetch raw HTML and available section IDs for a company page.
76
+ */
77
+ async getCompanyRaw(symbol, mode = "consolidated") {
78
+ const url = this.companyUrl(symbol, mode);
79
+ const html = await this.fetchHtml(url, "company");
80
+ const root = parseHtml(html);
81
+ return {
82
+ data: { symbol: symbol.toUpperCase(), html, sectionIds: parseSectionIds(root) },
83
+ meta: this.meta(url),
84
+ warnings: [],
85
+ };
86
+ }
87
+ /**
88
+ * Compare multiple companies side-by-side — returns a summary row per symbol.
89
+ */
90
+ async compareCompanies(symbols, mode = "consolidated") {
91
+ const results = await Promise.allSettled(symbols.map((s) => this.getCompany(s, mode)));
92
+ const warnings = [];
93
+ const summaries = [];
94
+ results.forEach((r, i) => {
95
+ if (r.status === "rejected") {
96
+ const msg = r.reason instanceof Error ? r.reason.message : String(r.reason);
97
+ warnings.push(`Failed to fetch ${symbols[i]}: ${msg}`);
98
+ return;
99
+ }
100
+ const { data } = r.value;
101
+ const ratio = (name) => data.topRatios.find((tr) => tr.name.toLowerCase().includes(name.toLowerCase()))?.value;
102
+ summaries.push({
103
+ symbol: data.symbol,
104
+ name: data.name,
105
+ marketCap: ratio("market cap"),
106
+ currentPrice: ratio("current price"),
107
+ pe: ratio("stock p/e") ?? ratio("p/e"),
108
+ roe: ratio("roe"),
109
+ dividendYield: ratio("dividend yield"),
110
+ });
111
+ });
112
+ return {
113
+ data: summaries,
114
+ meta: this.meta(`${this.config.baseUrl}/company/`),
115
+ warnings,
116
+ };
117
+ }
118
+ }
119
+ //# sourceMappingURL=company.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"company.js","sourceRoot":"","sources":["../../src/client/company.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { ClientConfig } from "../types.js";
2
+ import { SearchClient } from "./search.js";
3
+ /**
4
+ * ScreenerClient — scrapes screener.in for Indian stock market data.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const client = new ScreenerClient({ minIntervalMs: 300 });
9
+ * const { data } = await client.getCompany("TCS");
10
+ * ```
11
+ *
12
+ * For protected pages (screens, watchlist, announcements), pass a session cookie:
13
+ * ```ts
14
+ * const client = new ScreenerClient({ cookies: "sessionid=YOUR_SESSION_ID" });
15
+ * ```
16
+ */
17
+ export declare class ScreenerClient extends SearchClient {
18
+ constructor(config?: ClientConfig);
19
+ /** Clear all cached responses. */
20
+ clearCache(): void;
21
+ }
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,qBAAa,cAAe,SAAQ,YAAY;gBAClC,MAAM,GAAE,YAAiB;IAIrC,kCAAkC;IAClC,UAAU,IAAI,IAAI;CAGnB"}
@@ -0,0 +1,25 @@
1
+ import { SearchClient } from "./search.js";
2
+ /**
3
+ * ScreenerClient — scrapes screener.in for Indian stock market data.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const client = new ScreenerClient({ minIntervalMs: 300 });
8
+ * const { data } = await client.getCompany("TCS");
9
+ * ```
10
+ *
11
+ * For protected pages (screens, watchlist, announcements), pass a session cookie:
12
+ * ```ts
13
+ * const client = new ScreenerClient({ cookies: "sessionid=YOUR_SESSION_ID" });
14
+ * ```
15
+ */
16
+ export class ScreenerClient extends SearchClient {
17
+ constructor(config = {}) {
18
+ super(config);
19
+ }
20
+ /** Clear all cached responses. */
21
+ clearCache() {
22
+ this.cache.clear();
23
+ }
24
+ }
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC9C,YAAY,SAAuB,EAAE;QACnC,KAAK,CAAC,MAAM,CAAC,CAAC;IAChB,CAAC;IAED,kCAAkC;IAClC,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { ScreenItem, ScreenDetails, ListScreensOptions, ScreenDetailsOptions, ApiResponse } from "../types.js";
2
+ import { SectorClient } from "./sectors.js";
3
+ export declare abstract class ScreenClient extends SectorClient {
4
+ /**
5
+ * List public stock screens with optional filtering, sorting, and pagination.
6
+ */
7
+ listScreens(options?: ListScreensOptions): Promise<ApiResponse<ScreenItem[]>>;
8
+ /**
9
+ * Fetch detailed company list for a specific screen.
10
+ * Requires a session cookie for protected screens.
11
+ */
12
+ getScreenDetails(screenId: number, slug: string, options?: ScreenDetailsOptions): Promise<ApiResponse<ScreenDetails>>;
13
+ }
14
+ //# sourceMappingURL=screens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screens.d.ts","sourceRoot":"","sources":["../../src/client/screens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,8BAAsB,YAAa,SAAQ,YAAY;IACrD;;OAEG;IACG,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IAkDvF;;;OAGG;IACG,gBAAgB,CACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;CAuCvC"}
@@ -0,0 +1,88 @@
1
+ import { parseHtml, parseScreenItems, parseDataTable, parsePagination } from "../utils/parser.js";
2
+ import { SectorClient } from "./sectors.js";
3
+ export class ScreenClient extends SectorClient {
4
+ /**
5
+ * List public stock screens with optional filtering, sorting, and pagination.
6
+ */
7
+ async listScreens(options = {}) {
8
+ const { page = 1, includeAllPages = false, maxPages = 20, q, sort, order = "asc" } = options;
9
+ const fetchPage = async (p) => {
10
+ const url = `${this.config.baseUrl}/screens/?page=${p}`;
11
+ const html = await this.fetchHtml(url, "screens");
12
+ return parseScreenItems(parseHtml(html));
13
+ };
14
+ let items = await fetchPage(page);
15
+ if (includeAllPages) {
16
+ for (let p = page + 1; p <= maxPages; p++) {
17
+ const more = await fetchPage(p);
18
+ if (more.length === 0)
19
+ break;
20
+ items.push(...more);
21
+ }
22
+ // Deduplicate by id
23
+ const seen = new Set();
24
+ items = items.filter((it) => {
25
+ if (seen.has(it.id))
26
+ return false;
27
+ seen.add(it.id);
28
+ return true;
29
+ });
30
+ }
31
+ // Client-side filtering
32
+ if (q) {
33
+ const lq = q.toLowerCase();
34
+ items = items.filter((it) => it.title.toLowerCase().includes(lq) || it.description.toLowerCase().includes(lq));
35
+ }
36
+ // Client-side sorting
37
+ if (sort === "title") {
38
+ items.sort((a, b) => order === "asc" ? a.title.localeCompare(b.title) : b.title.localeCompare(a.title));
39
+ }
40
+ else if (sort === "id") {
41
+ items.sort((a, b) => (order === "asc" ? a.id - b.id : b.id - a.id));
42
+ }
43
+ return {
44
+ data: items,
45
+ meta: this.meta(`${this.config.baseUrl}/screens/?page=${page}`),
46
+ warnings: [],
47
+ };
48
+ }
49
+ /**
50
+ * Fetch detailed company list for a specific screen.
51
+ * Requires a session cookie for protected screens.
52
+ */
53
+ async getScreenDetails(screenId, slug, options = {}) {
54
+ const { page = 1, limit = 50, includeAllPages = false } = options;
55
+ const fetchPage = async (p) => {
56
+ const url = `${this.config.baseUrl}/screens/${screenId}/${slug}/?page=${p}&limit=${limit}`;
57
+ const html = await this.fetchHtml(url, "screens");
58
+ const root = parseHtml(html);
59
+ return { root, url };
60
+ };
61
+ const { root, url } = await fetchPage(page);
62
+ const { columns, rows } = parseDataTable(root);
63
+ const { totalPages } = parsePagination(root);
64
+ const titleEl = root.querySelector("h1, .screen-title, title");
65
+ const title = titleEl?.text.trim().split("|")[0].trim() ?? `Screen #${screenId}`;
66
+ const allRows = rows;
67
+ const warnings = [];
68
+ if (includeAllPages) {
69
+ for (let p = page + 1; p <= totalPages; p++) {
70
+ try {
71
+ const { root: r } = await fetchPage(p);
72
+ const { rows: moreRows } = parseDataTable(r);
73
+ allRows.push(...moreRows);
74
+ }
75
+ catch (err) {
76
+ const msg = err instanceof Error ? err.message : String(err);
77
+ warnings.push(`Failed to fetch page ${p}: ${msg}`);
78
+ }
79
+ }
80
+ }
81
+ return {
82
+ data: { id: screenId, slug, title, columns, rows: allRows, page, totalPages },
83
+ meta: this.meta(url),
84
+ warnings,
85
+ };
86
+ }
87
+ }
88
+ //# sourceMappingURL=screens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screens.js","sourceRoot":"","sources":["../../src/client/screens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { SearchResult, ApiResponse } from "../types.js";
2
+ import { ScreenClient } from "./screens.js";
3
+ export declare abstract class SearchClient extends ScreenClient {
4
+ /**
5
+ * Search companies by name or symbol using the screener.in JSON search API.
6
+ * Returns real company names (not just symbols like the old sitemap approach).
7
+ */
8
+ searchCompanies(query: string, limit?: number): Promise<ApiResponse<SearchResult[]>>;
9
+ }
10
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/client/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,8BAAsB,YAAa,SAAQ,YAAY;IACrD;;;OAGG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;CA6BvF"}
@@ -0,0 +1,35 @@
1
+ import { retryWithBackoff } from "../utils/retry.js";
2
+ import { ScreenClient } from "./screens.js";
3
+ export class SearchClient extends ScreenClient {
4
+ /**
5
+ * Search companies by name or symbol using the screener.in JSON search API.
6
+ * Returns real company names (not just symbols like the old sitemap approach).
7
+ */
8
+ async searchCompanies(query, limit = 10) {
9
+ const apiUrl = `${this.config.baseUrl}/api/company/search/?q=${encodeURIComponent(query)}&limit=${limit}`;
10
+ await this.throttle.wait("search");
11
+ const res = await retryWithBackoff(async () => {
12
+ return this.http.get(apiUrl, {
13
+ headers: { Accept: "application/json" },
14
+ });
15
+ }, this.config.maxRetries);
16
+ const items = Array.isArray(res.data) ? res.data : [];
17
+ const results = items.slice(0, limit).map((item) => {
18
+ const match = item.url?.match(/\/company\/([^/]+)\//);
19
+ const symbol = match?.[1] ?? item.name;
20
+ return {
21
+ symbol,
22
+ name: item.name,
23
+ url: item.url
24
+ ? `${this.config.baseUrl}${item.url}`
25
+ : `${this.config.baseUrl}/company/${symbol}/`,
26
+ };
27
+ });
28
+ return {
29
+ data: results,
30
+ meta: this.meta(apiUrl),
31
+ warnings: results.length === 0 ? ["No results found for the given query"] : [],
32
+ };
33
+ }
34
+ }
35
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/client/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,OAAgB,YAAa,SAAQ,YAAY;IACrD;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,KAAa,EAAE,KAAK,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,0BAA0B,kBAAkB,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,CAAC;QAC1G,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEnC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,KAAK,IAAI,EAAE;YAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAmD,MAAM,EAAE;gBAC7E,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;aACxC,CAAC,CAAC;QACL,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAE3B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,OAAO,GAAmB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACjE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;YACvC,OAAO;gBACL,MAAM;gBACN,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,GAAG,EAAE,IAAI,CAAC,GAAG;oBACX,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE;oBACrC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,YAAY,MAAM,GAAG;aAChD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACvB,QAAQ,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,sCAAsC,CAAC,CAAC,CAAC,CAAC,EAAE;SAC/E,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import type { SectorItem, SectorData, SectorDataOptions, ApiResponse } from "../types.js";
2
+ import { CompanyClient } from "./company.js";
3
+ export declare abstract class SectorClient extends CompanyClient {
4
+ /**
5
+ * List all sectors available on screener.in.
6
+ */
7
+ listSectors(): Promise<ApiResponse<SectorItem[]>>;
8
+ /**
9
+ * Fetch companies in a sector with optional pagination.
10
+ * Pass `includeAllPages: true` to auto-fetch every page.
11
+ */
12
+ getSectorData(sector: string, options?: SectorDataOptions): Promise<ApiResponse<SectorData>>;
13
+ private _getAllSectorPages;
14
+ }
15
+ //# sourceMappingURL=sectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sectors.d.ts","sourceRoot":"","sources":["../../src/client/sectors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1F,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,8BAAsB,YAAa,SAAQ,aAAa;IACtD;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;IASvD;;;OAGG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YAoBrB,kBAAkB;CAwBjC"}
@@ -0,0 +1,55 @@
1
+ import { parseHtml, parseSectorLinks, parseDataTable, parsePagination } from "../utils/parser.js";
2
+ import { CompanyClient } from "./company.js";
3
+ export class SectorClient extends CompanyClient {
4
+ /**
5
+ * List all sectors available on screener.in.
6
+ */
7
+ async listSectors() {
8
+ const url = `${this.config.baseUrl}/market/`;
9
+ const html = await this.fetchHtml(url, "sector");
10
+ const root = parseHtml(html);
11
+ const sectors = parseSectorLinks(root);
12
+ return { data: sectors, meta: this.meta(url), warnings: [] };
13
+ }
14
+ /**
15
+ * Fetch companies in a sector with optional pagination.
16
+ * Pass `includeAllPages: true` to auto-fetch every page.
17
+ */
18
+ async getSectorData(sector, options = {}) {
19
+ const { page = 1, limit = 50, includeAllPages = false } = options;
20
+ if (includeAllPages) {
21
+ return this._getAllSectorPages(sector, limit);
22
+ }
23
+ const url = `${this.config.baseUrl}/market/${sector}/?limit=${limit}&page=${page}`;
24
+ const html = await this.fetchHtml(url, "sector");
25
+ const root = parseHtml(html);
26
+ const { columns, rows } = parseDataTable(root);
27
+ const { totalPages } = parsePagination(root);
28
+ return {
29
+ data: { sector, columns, rows, page, totalPages, totalResults: rows.length },
30
+ meta: this.meta(url),
31
+ warnings: [],
32
+ };
33
+ }
34
+ async _getAllSectorPages(sector, limit) {
35
+ const first = await this.getSectorData(sector, { page: 1, limit });
36
+ const allRows = [...first.data.rows];
37
+ const warnings = [];
38
+ for (let p = 2; p <= first.data.totalPages; p++) {
39
+ try {
40
+ const page = await this.getSectorData(sector, { page: p, limit });
41
+ allRows.push(...page.data.rows);
42
+ }
43
+ catch (err) {
44
+ const msg = err instanceof Error ? err.message : String(err);
45
+ warnings.push(`Failed to fetch page ${p}: ${msg}`);
46
+ }
47
+ }
48
+ return {
49
+ data: { ...first.data, rows: allRows, totalResults: allRows.length, page: 1 },
50
+ meta: first.meta,
51
+ warnings,
52
+ };
53
+ }
54
+ }
55
+ //# sourceMappingURL=sectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sectors.js","sourceRoot":"","sources":["../../src/client/sectors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { ScreenerClient } from "./client/index.js";
2
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
package/lib/client.js ADDED
@@ -0,0 +1,3 @@
1
+ // Re-export from the structured client folder
2
+ export { ScreenerClient } from "./client/index.js";
3
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { ScreenerClient } from "./client.js";
2
+ export type { ClientConfig, CompanyMode, CompanyTab, CompanyData, CompanyRaw, CompanySummary, TopRatio, FinancialTable, TableRow, AnalysisData, DocumentLink, PeerRow, SectorItem, SectorData, SectorDataOptions, ScreenItem, ScreenDetails, ScreenDetailsOptions, ListScreensOptions, SearchResult, ApiResponse, Meta, } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,IAAI,GACL,MAAM,YAAY,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { ScreenerClient } from "./client.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}