bharosa 0.5.1 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ Add `markets.schemes.search` and compatible `BharosaMarket.schemes.search` using the canonical account-independent search route. Keep private search and historical methods unchanged. Correct the getting-started example to use an API key without a required account ID.
6
+
7
+
3
8
  ## 0.5.1
4
9
 
5
10
  Documentation-only correction: use normal npm installation and released status, describe deployed unified-key/latest-NAV access, and remove stale preview wording. Runtime, public types, contracts and dependencies are unchanged from 0.5.0.
@@ -0,0 +1 @@
1
+ 49577eff1da1c0b5badeb61136ee64f8ed35eab4e68f040d4341016475d4d646
package/README.md CHANGED
@@ -135,3 +135,18 @@ Adds `mutualFundSchemes.performance.retrieve` and `fundCategories.statistics.ret
135
135
  SDK 0.5.0 introduced `new Bharosa({ apiKey })` and `client.markets`, using the existing account-independent market routes. Omit the NAV selection for latest NAV, or pass `{ asOf: "2026-10-01" }` for a monthly snapshot. Missing observations return `status: "missing"` and `data: null`. Explicit dates must be month starts. The account-scoped NAV method also accepts omission, while keeping account authorization.
136
136
 
137
137
  Existing `auth` configurations and `BharosaMarket` remain supported. Baseline calls use only the API key; delegated private calls still require user consent and a valid user token. The production origin remains `https://api.bharosa.finance`. Unified-key support is deployed. Private permissions remain optional and are enforced by the server; installing the SDK grants no additional access.
138
+
139
+ ## Find a scheme with baseline market access
140
+
141
+ ```ts
142
+ const choices = await bharosa.markets.schemes.search({ query: "equity", limit: 5 });
143
+ const selected = choices.data[0];
144
+ if (selected) {
145
+ const nav = await bharosa.markets.schemes.nav(selected.scheme_id);
146
+ console.log(selected.plan_label, selected.option_label, nav.status);
147
+ }
148
+ ```
149
+
150
+ Choose the intended scheme and plan from the results. `query` must have 2–100 characters, with at least two after trimming; `limit` is 1–20 and defaults to 10. If `has_more` is true, refine the query; search has no cursor or historical date parameter. An empty `data` array is a valid result. Search returns scheme identities and latest NAV references, including freshness and data-mode information. It does not grant private account access. Existing `mutualFunds.search` remains account-scoped. `BharosaMarket` users can call `schemes.search` directly.
151
+
152
+ Available in SDK 0.6.0 and later, using the account-independent `/v1/market-data/schemes/search` route.
package/dist/index.cjs CHANGED
@@ -399,7 +399,7 @@ class Bharosa {
399
399
  }
400
400
  }
401
401
  exports.Bharosa = Bharosa;
402
- /** Server-only registered-app monthly market access. No account or user token. */
402
+ /** Server-only baseline market access. No account or user token. */
403
403
  class BharosaMarket {
404
404
  schemes;
405
405
  funds;
@@ -431,6 +431,11 @@ function baselineMarkets(call) {
431
431
  };
432
432
  };
433
433
  const schemes = {
434
+ search: async (p, o) => {
435
+ (0, transport_cjs_1.keys)(p, ["query", "limit"]);
436
+ (0, transport_cjs_1.check)(typeof p.query === "string" && p.query.trim().length >= 2 && p.query.length <= 100);
437
+ return call("searchMarketSchemes", p, undefined, o);
438
+ },
434
439
  nav: (id, q = {}, o) => {
435
440
  (0, transport_cjs_1.keys)(q, ["asOf"]);
436
441
  return call("monthly_nav", { id, ...(q.asOf === undefined ? {} : { as_of: q.asOf }) }, undefined, o);
package/dist/index.d.cts CHANGED
@@ -2,6 +2,7 @@ export type * from "./analytics-types.cjs";
2
2
  import type { MonthlyMarketClient } from "./monthly-types.cjs";
3
3
  export type * from "./monthly-types.cjs";
4
4
  import type * as T from "./client-types.cjs";
5
+ import type * as M from "./models.cjs";
5
6
  import type * as D from "./market-types.cjs";
6
7
  export type * from "./client-types.cjs";
7
8
  export * from "./errors.cjs";
@@ -26,7 +27,7 @@ export interface BharosaMarketConfig {
26
27
  maxResponseBytes?: number;
27
28
  fetch?: typeof globalThis.fetch;
28
29
  }
29
- /** Server-only registered-app monthly market access. No account or user token. */
30
+ /** Server-only baseline market access. No account or user token. */
30
31
  export declare class BharosaMarket {
31
32
  readonly schemes: BaselineMarketClient["schemes"];
32
33
  readonly funds: MonthlyMarketClient["funds"];
@@ -34,6 +35,10 @@ export declare class BharosaMarket {
34
35
  }
35
36
  export interface BaselineMarketClient {
36
37
  readonly schemes: {
38
+ search(query: {
39
+ query: string;
40
+ limit?: number;
41
+ }, options?: T.RequestOptions): Promise<M.FundsList>;
37
42
  nav(id: string, selection?: {
38
43
  asOf?: string;
39
44
  }, options?: T.RequestOptions): ReturnType<MonthlyMarketClient["schemes"]["nav"]>;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export type * from "./analytics-types.js";
2
2
  import type { MonthlyMarketClient } from "./monthly-types.js";
3
3
  export type * from "./monthly-types.js";
4
4
  import type * as T from "./client-types.js";
5
+ import type * as M from "./models.js";
5
6
  import type * as D from "./market-types.js";
6
7
  export type * from "./client-types.js";
7
8
  export * from "./errors.js";
@@ -26,7 +27,7 @@ export interface BharosaMarketConfig {
26
27
  maxResponseBytes?: number;
27
28
  fetch?: typeof globalThis.fetch;
28
29
  }
29
- /** Server-only registered-app monthly market access. No account or user token. */
30
+ /** Server-only baseline market access. No account or user token. */
30
31
  export declare class BharosaMarket {
31
32
  readonly schemes: BaselineMarketClient["schemes"];
32
33
  readonly funds: MonthlyMarketClient["funds"];
@@ -34,6 +35,10 @@ export declare class BharosaMarket {
34
35
  }
35
36
  export interface BaselineMarketClient {
36
37
  readonly schemes: {
38
+ search(query: {
39
+ query: string;
40
+ limit?: number;
41
+ }, options?: T.RequestOptions): Promise<M.FundsList>;
37
42
  nav(id: string, selection?: {
38
43
  asOf?: string;
39
44
  }, options?: T.RequestOptions): ReturnType<MonthlyMarketClient["schemes"]["nav"]>;
@@ -0,0 +1,357 @@
1
+ "use strict";
2
+ // Generated from the canonical market search contract; all references resolved locally.
3
+ module.exports = {
4
+ "operations": {
5
+ "searchMarketSchemes": {
6
+ "path": "/v1/market-data/schemes/search",
7
+ "method": "GET",
8
+ "status": 200,
9
+ "marketData": true,
10
+ "readOnly": true,
11
+ "parameters": [
12
+ {
13
+ "name": "query",
14
+ "in": "query",
15
+ "required": true,
16
+ "description": "2–100 characters. Case-insensitive label and identifier search; percent and underscore are literal.",
17
+ "schema": {
18
+ "type": "string",
19
+ "minLength": 2,
20
+ "maxLength": 100
21
+ }
22
+ },
23
+ {
24
+ "name": "limit",
25
+ "in": "query",
26
+ "required": false,
27
+ "description": "1–20; default 10. Search is a bounded result set, not cursor pagination.",
28
+ "schema": {
29
+ "type": "integer",
30
+ "minimum": 1,
31
+ "maximum": 20,
32
+ "default": 10
33
+ }
34
+ }
35
+ ],
36
+ "response": {
37
+ "type": "object",
38
+ "properties": {
39
+ "object": {
40
+ "const": "list"
41
+ },
42
+ "data": {
43
+ "type": "array",
44
+ "items": {
45
+ "type": "object",
46
+ "properties": {
47
+ "instrument": {
48
+ "type": "object",
49
+ "properties": {
50
+ "id": {
51
+ "type": "string",
52
+ "pattern": "^ins_[A-Za-z0-9_-]{1,150}$"
53
+ },
54
+ "object": {
55
+ "const": "instrument"
56
+ },
57
+ "created": {
58
+ "type": "integer",
59
+ "minimum": 0,
60
+ "maximum": 9007199254740991
61
+ },
62
+ "name": {
63
+ "type": "string",
64
+ "minLength": 1,
65
+ "maxLength": 200,
66
+ "pattern": "\\S"
67
+ },
68
+ "identifiers": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "properties": {
73
+ "namespace": {
74
+ "type": "string"
75
+ },
76
+ "value": {
77
+ "type": "string"
78
+ }
79
+ },
80
+ "required": [
81
+ "namespace",
82
+ "value"
83
+ ],
84
+ "additionalProperties": true
85
+ }
86
+ },
87
+ "domicile_country": {
88
+ "anyOf": [
89
+ {
90
+ "type": "string"
91
+ },
92
+ {
93
+ "type": "null"
94
+ }
95
+ ]
96
+ },
97
+ "type": {
98
+ "const": "mutual_fund"
99
+ },
100
+ "mutual_fund": {
101
+ "type": "object",
102
+ "properties": {
103
+ "fund_name": {
104
+ "type": "string",
105
+ "minLength": 1,
106
+ "maxLength": 200,
107
+ "pattern": "\\S"
108
+ },
109
+ "share_class": {
110
+ "anyOf": [
111
+ {
112
+ "type": "string"
113
+ },
114
+ {
115
+ "type": "null"
116
+ }
117
+ ]
118
+ },
119
+ "class_currency": {
120
+ "anyOf": [
121
+ {
122
+ "type": "string"
123
+ },
124
+ {
125
+ "type": "null"
126
+ }
127
+ ]
128
+ },
129
+ "distribution_policy": {
130
+ "type": "string",
131
+ "x-known-values": [
132
+ "accumulating",
133
+ "distributing",
134
+ "unknown"
135
+ ],
136
+ "minLength": 1
137
+ }
138
+ },
139
+ "required": [
140
+ "fund_name",
141
+ "share_class",
142
+ "class_currency",
143
+ "distribution_policy"
144
+ ],
145
+ "additionalProperties": true
146
+ }
147
+ },
148
+ "required": [
149
+ "id",
150
+ "object",
151
+ "created",
152
+ "name",
153
+ "identifiers",
154
+ "domicile_country",
155
+ "type",
156
+ "mutual_fund"
157
+ ],
158
+ "additionalProperties": true
159
+ },
160
+ "market": {
161
+ "const": "IN"
162
+ },
163
+ "currency": {
164
+ "const": "INR"
165
+ },
166
+ "scheme_id": {
167
+ "type": "string",
168
+ "minLength": 1,
169
+ "description": "Opaque catalogue identifier; production bridge accepts validated positive decimal scheme IDs, fixture IDs are not DB IDs."
170
+ },
171
+ "plan_label": {
172
+ "type": "string"
173
+ },
174
+ "option_label": {
175
+ "type": "string"
176
+ },
177
+ "amfi_code": {
178
+ "anyOf": [
179
+ {
180
+ "type": "string"
181
+ },
182
+ {
183
+ "type": "null"
184
+ }
185
+ ]
186
+ },
187
+ "isin": {
188
+ "anyOf": [
189
+ {
190
+ "type": "string"
191
+ },
192
+ {
193
+ "type": "null"
194
+ }
195
+ ]
196
+ },
197
+ "identity_status": {
198
+ "type": "string",
199
+ "x-known-values": [
200
+ "resolved",
201
+ "conflict"
202
+ ],
203
+ "minLength": 1
204
+ },
205
+ "latest_nav": {
206
+ "anyOf": [
207
+ {
208
+ "type": "object",
209
+ "properties": {
210
+ "amount": {
211
+ "type": "string",
212
+ "pattern": "^(0|[1-9][0-9]{0,19})(\\.[0-9]{1,18})?$"
213
+ },
214
+ "currency": {
215
+ "const": "INR"
216
+ },
217
+ "date": {
218
+ "type": "string",
219
+ "format": "date",
220
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
221
+ "description": "Real calendar date, 1900-01-01 through today Asia/Kolkata; replacement cannot move backwards."
222
+ }
223
+ },
224
+ "required": [
225
+ "amount",
226
+ "currency",
227
+ "date"
228
+ ],
229
+ "additionalProperties": true
230
+ },
231
+ {
232
+ "type": "null"
233
+ }
234
+ ]
235
+ },
236
+ "data_mode": {
237
+ "type": "string",
238
+ "x-known-values": [
239
+ "live",
240
+ "fixture"
241
+ ],
242
+ "minLength": 1
243
+ },
244
+ "source": {
245
+ "type": "string"
246
+ },
247
+ "freshness": {
248
+ "type": "object",
249
+ "properties": {
250
+ "status": {
251
+ "type": "string",
252
+ "x-known-values": [
253
+ "recent",
254
+ "stale",
255
+ "missing",
256
+ "invalid",
257
+ "fixture"
258
+ ],
259
+ "minLength": 1
260
+ },
261
+ "checked_at": {
262
+ "type": "string",
263
+ "format": "date-time"
264
+ },
265
+ "as_of": {
266
+ "type": "string",
267
+ "format": "date",
268
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
269
+ "description": "Real calendar date, 1900-01-01 through today Asia/Kolkata; replacement cannot move backwards."
270
+ },
271
+ "time_zone": {
272
+ "const": "Asia/Kolkata"
273
+ },
274
+ "age_days": {
275
+ "anyOf": [
276
+ {
277
+ "type": "integer"
278
+ },
279
+ {
280
+ "type": "null"
281
+ }
282
+ ]
283
+ },
284
+ "recent_within_days": {
285
+ "const": 3
286
+ }
287
+ },
288
+ "required": [
289
+ "status",
290
+ "checked_at",
291
+ "as_of",
292
+ "time_zone",
293
+ "age_days",
294
+ "recent_within_days"
295
+ ],
296
+ "additionalProperties": true
297
+ }
298
+ },
299
+ "required": [
300
+ "instrument",
301
+ "market",
302
+ "currency",
303
+ "scheme_id",
304
+ "plan_label",
305
+ "option_label",
306
+ "amfi_code",
307
+ "isin",
308
+ "identity_status",
309
+ "latest_nav",
310
+ "data_mode",
311
+ "source",
312
+ "freshness"
313
+ ],
314
+ "additionalProperties": true
315
+ }
316
+ },
317
+ "has_more": {
318
+ "type": "boolean"
319
+ },
320
+ "url": {
321
+ "type": "string"
322
+ },
323
+ "market_data": {
324
+ "type": "object",
325
+ "properties": {
326
+ "mode": {
327
+ "type": "string",
328
+ "x-known-values": [
329
+ "live",
330
+ "fixture",
331
+ "unavailable"
332
+ ],
333
+ "minLength": 1
334
+ },
335
+ "notice": {
336
+ "type": "string"
337
+ }
338
+ },
339
+ "required": [
340
+ "mode",
341
+ "notice"
342
+ ],
343
+ "additionalProperties": true
344
+ }
345
+ },
346
+ "required": [
347
+ "object",
348
+ "data",
349
+ "has_more",
350
+ "url",
351
+ "market_data"
352
+ ],
353
+ "additionalProperties": true
354
+ }
355
+ }
356
+ }
357
+ };
@@ -0,0 +1,2 @@
1
+ import type { Operation } from "./schema.cjs";
2
+ export const operations: Readonly<Record<string, Operation>>;
@@ -0,0 +1,2 @@
1
+ import type { Operation } from "./schema.js";
2
+ export const operations: Readonly<Record<string, Operation>>;
@@ -5,6 +5,7 @@ import type * as D from "./market-types.cjs";
5
5
  import type { CurrentMixEvidence } from "./client-types.cjs";
6
6
  /** Each entry is the decoded response of the corresponding generated operation. */
7
7
  export interface OperationResults {
8
+ searchMarketSchemes: M.FundsList;
8
9
  analytics_scheme: A.SchemePerformance;
9
10
  analytics_category: A.CategoryStatistics;
10
11
  monthly_nav: S.MarketSnapshot<D.NavObservation>;
@@ -5,6 +5,7 @@ import type * as D from "./market-types.js";
5
5
  import type { CurrentMixEvidence } from "./client-types.js";
6
6
  /** Each entry is the decoded response of the corresponding generated operation. */
7
7
  export interface OperationResults {
8
+ searchMarketSchemes: M.FundsList;
8
9
  analytics_scheme: A.SchemePerformance;
9
10
  analytics_category: A.CategoryStatistics;
10
11
  monthly_nav: S.MarketSnapshot<D.NavObservation>;
@@ -55,6 +55,11 @@ function responseMatches(id, op, data, params, body, account) {
55
55
  (typeof params.limit === "number" && page.length > params.limit))
56
56
  return false;
57
57
  }
58
+ if (id === "searchMarketSchemes") {
59
+ const page = rows(d("data"));
60
+ if (d("url") !== op.path || page.length > (typeof params.limit === "number" ? params.limit : 10) || (d("has_more") === true && page.length === 0))
61
+ return false;
62
+ }
58
63
  if (op.marketData) {
59
64
  if (id.endsWith("_get") && d("id") !== params.id)
60
65
  return false;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.check = check;
4
4
  exports.keys = keys;
5
5
  exports.createTransport = createTransport;
6
+ const market_search_cjs_1 = require("./market-search.cjs");
6
7
  const analytics_contract_cjs_1 = require("./analytics-contract.cjs");
7
8
  const monthly_market_data_cjs_1 = require("./monthly-market-data.cjs");
8
9
  const contract_cjs_1 = require("./contract.cjs");
@@ -15,6 +16,7 @@ const operations = {
15
16
  ...market_data_cjs_1.operations,
16
17
  ...monthly_market_data_cjs_1.operations,
17
18
  ...analytics_contract_cjs_1.operations,
19
+ ...market_search_cjs_1.operations,
18
20
  };
19
21
  function assertServer() {
20
22
  if (typeof window !== "undefined" ||
@@ -209,7 +211,7 @@ function createTransport(input, marketOnly = false) {
209
211
  const call = async (id, params = {}, body, opts = {}) => {
210
212
  const op = operations[id];
211
213
  if (marketOnly &&
212
- !["monthly_nav", "monthly_expense", "monthly_portfolio", "monthly_holdings"].includes(id)) {
214
+ !["monthly_nav", "monthly_expense", "monthly_portfolio", "monthly_holdings", "searchMarketSchemes"].includes(id)) {
213
215
  throw Object.assign(new errors_cjs_1.ValidationError(), { code: "market_only_operation" });
214
216
  }
215
217
  let o, serialized, url;
@@ -16,6 +16,8 @@ Source contributors can build and pack a local archive as described in CONTRIBUT
16
16
 
17
17
  ## Read your account
18
18
 
19
+ This call requires the optional own-account read permission. An account ID is not a prerequisite: the API-key shorthand selects `me`. Use an explicit `account` only when needed; delegated access uses the server-authorized account.
20
+
19
21
  In an ESM application, save this as `account.mjs`:
20
22
 
21
23
  ```js
@@ -28,14 +30,13 @@ function required(name) {
28
30
  }
29
31
 
30
32
  const bharosa = new Bharosa({
31
- account: required("BHAROSA_ACCOUNT_ID"),
32
- auth: { type: "account_key", apiKey: required("BHAROSA_SECRET_KEY") },
33
+ apiKey: required("BHAROSA_SECRET_KEY"),
33
34
  });
34
35
  const account = await bharosa.accounts.retrieve();
35
36
  console.log(account.id);
36
37
  ```
37
38
 
38
- Supply those variables through your application's secret management, then run `node account.mjs`. Do not commit their values. For another deployment or tests, explicitly supply `baseUrl`. It must use HTTPS and contain no path, query, user information, or fragment; local HTTP additionally requires `allowLocalhostHttp: true`. Invalid explicit origins fail before sending a request.
39
+ Supply `BHAROSA_SECRET_KEY` through your application's secret management, then run `node account.mjs`. Do not commit their values. For another deployment or tests, explicitly supply `baseUrl`. It must use HTTPS and contain no path, query, user information, or fragment; local HTTP additionally requires `allowLocalhostHttp: true`. Invalid explicit origins fail before sending a request.
39
40
 
40
41
  CommonJS applications use `const { Bharosa } = require("bharosa")` inside an async function. TypeScript applications import types from the same root package; do not import files from `dist/`.
41
42
 
@@ -11,7 +11,9 @@ const monthly = await client.markets.schemes.nav("45139", { asOf: "2026-10-01" }
11
11
 
12
12
  Baseline methods are `markets.schemes.nav`, `markets.schemes.expenseRatio`, `markets.funds.portfolio` and `markets.funds.holdings`. Omit the NAV selection for latest NAV; all explicit historical dates must be month starts. The remaining three methods require a monthly selection. `BharosaMarket` exposes the same baseline methods without the `markets` prefix.
13
13
 
14
- The discovery and account-scoped methods below require their existing account permissions. A baseline-only key does not gain access to scheme search or private analytics.
14
+ SDK 0.6.0 adds baseline discovery through `client.markets.schemes.search({ query: "equity", limit: 5 })`, returning `data`, `has_more`, `url` and `market_data`. Use a returned `scheme_id` for NAV and expense methods. Choose among the plan/option labels; do not assume the first result is the intended investment. Refine the query when `has_more` is true; no cursor or historical selection is accepted. Search uses the account-independent `/v1/market-data/schemes/search` route.
15
+
16
+ The existing account-scoped discovery and analytics methods below retain their account permissions. Baseline access never grants private analytics.
15
17
 
16
18
  Resolve an investible scheme through `client.mutualFunds.search()` and its returned `scheme_id`. Fund-owner IDs and scheme IDs are distinct: NAV and expense ratios belong to schemes; portfolio snapshots and holdings belong to fund owners. Do not use an AMC ID as a fund-owner ID.
17
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bharosa",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "description": "Typed Bharosa resource SDK with server credentials or caller-owned transport.",
6
6
  "license": "MIT",
@@ -45,7 +45,8 @@
45
45
  "CHANGELOG.md",
46
46
  "FIRST-PARTY-CONTRACT-SHA256",
47
47
  "MONTHLY-MARKET-CONTRACT-SHA256",
48
- "ANALYTICS-CONTRACT-SHA256"
48
+ "ANALYTICS-CONTRACT-SHA256",
49
+ "MARKET-SEARCH-CONTRACT-SHA256"
49
50
  ],
50
51
  "scripts": {
51
52
  "build": "node scripts/build.mjs",
@@ -61,7 +62,9 @@
61
62
  "generate:monthly": "node scripts/generate-monthly.mjs",
62
63
  "check:monthly": "node scripts/generate-monthly.mjs --check",
63
64
  "generate:analytics": "node scripts/generate-analytics.mjs",
64
- "check:analytics": "node scripts/generate-analytics.mjs --check"
65
+ "check:analytics": "node scripts/generate-analytics.mjs --check",
66
+ "generate:market-search": "node scripts/generate-market-search.mjs",
67
+ "check:market-search": "node scripts/generate-market-search.mjs --check"
65
68
  },
66
69
  "publishConfig": {
67
70
  "access": "public",