openfigi-sdk 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # openfigi-sdk
2
+
3
+ A modern, type-safe TypeScript SDK for the [OpenFIGI API](https://www.openfigi.com/api) - the free and open standard for financial instrument identification.
4
+
5
+ [![CI](https://github.com/viktorlarsson/openfigi/actions/workflows/ci.yml/badge.svg)](https://github.com/viktorlarsson/openfigi/actions/workflows/ci.yml)
6
+ [![npm version](https://badge.fury.io/js/openfigi-sdk.svg)](https://www.npmjs.com/package/openfigi-sdk)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ > **⚠️ Community Project Disclaimer**
10
+ > This is an **unofficial, community-maintained** TypeScript SDK for OpenFIGI. It is **not affiliated with or endorsed by OpenFIGI or Bloomberg**. This library is developed and maintained by the open-source community. For official support, please refer to the [OpenFIGI official documentation](https://www.openfigi.com/api).
11
+
12
+ ## Features
13
+
14
+ - **Type-safe** - Full TypeScript support with comprehensive type definitions
15
+ - **Modern** - Built with latest technologies (Bun, Vitest, Biome, tsup)
16
+ - **Validated** - Runtime validation using Zod schemas
17
+ - **Resilient** - Built-in retry logic with exponential backoff
18
+ - **Rate Limiting** - Automatic rate limit handling
19
+ - **Developer Friendly** - Simple API with convenience methods
20
+ - **Well Tested** - Comprehensive test coverage
21
+ - **Tree-shakeable** - Optimized bundle size with ESM/CJS support
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ # Using bun
27
+ bun add openfigi-sdk
28
+
29
+ # Using npm
30
+ npm install openfigi-sdk
31
+
32
+ # Using pnpm
33
+ pnpm add openfigi-sdk
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ```typescript
39
+ import { searchByISIN, searchByCUSIP, searchByTicker, searchBySEDOL, searchByBloombergId, createClient } from 'openfigi-sdk'
40
+
41
+ // Use standalone functions (no API key required for public access)
42
+ const response = await searchByISIN('US0378331005')
43
+ console.log(response.data)
44
+
45
+ // Search by CUSIP
46
+ await searchByCUSIP('037833100')
47
+
48
+ // Search by ticker symbol
49
+ await searchByTicker('AAPL', 'US')
50
+
51
+ // Search by SEDOL
52
+ await searchBySEDOL('2046251')
53
+
54
+ // Search by Bloomberg ID
55
+ await searchByBloombergId('BBG000B9XRY4')
56
+
57
+ // Or create a client with custom configuration (e.g., API key for higher rate limits)
58
+ const client = createClient({
59
+ apiKey: 'your-api-key-here',
60
+ timeout: 60000
61
+ })
62
+
63
+ const result = await client.searchByISIN('US0378331005')
64
+ ```
65
+
66
+ ## API Reference
67
+
68
+ ### Client Configuration
69
+
70
+ ```typescript
71
+ interface ClientConfig {
72
+ apiKey?: string // OpenFIGI API key for higher rate limits
73
+ baseUrl?: string // API base URL (default: https://api.openfigi.com)
74
+ timeout?: number // Request timeout in ms (default: 30000)
75
+ retryLimit?: number // Number of retry attempts (default: 3)
76
+ retryDelay?: number // Initial retry delay in ms (default: 1000)
77
+ userAgent?: string // Custom user agent
78
+ }
79
+ ```
80
+
81
+ ### Batch Mapping
82
+
83
+ ```typescript
84
+ import { mapping, createClient } from 'openfigi-sdk'
85
+
86
+ // Map multiple identifiers in a single request (max 100)
87
+ const requests = [
88
+ { idType: 'ID_ISIN', idValue: 'US0378331005' },
89
+ { idType: 'ID_CUSIP', idValue: '037833100' },
90
+ { idType: 'ID_SEDOL', idValue: '2046251' }
91
+ ]
92
+
93
+ // Using standalone function
94
+ const responses = await mapping(requests)
95
+
96
+ // Or with custom client
97
+ const client = createClient({ apiKey: 'your-key' })
98
+ const responses = await client.mapping(requests)
99
+
100
+ responses.forEach((response, index) => {
101
+ if (response.data) {
102
+ console.log(`Request ${index}:`, response.data)
103
+ } else if (response.error) {
104
+ console.error(`Request ${index} failed:`, response.error)
105
+ }
106
+ })
107
+ ```
108
+
109
+ ### Advanced Search Options
110
+
111
+ ```typescript
112
+ import { searchByISIN, mappingSingle } from 'openfigi-sdk'
113
+
114
+ // Search with additional filters
115
+ const response = await searchByISIN('US0378331005', {
116
+ exchCode: 'US',
117
+ currency: 'USD',
118
+ marketSecDes: 'Equity',
119
+ includeUnlistedEquities: false
120
+ })
121
+
122
+ // Custom mapping request
123
+ const response = await mappingSingle({
124
+ idType: 'ID_BB_GLOBAL',
125
+ idValue: 'BBG000B9XRY4',
126
+ currency: 'USD',
127
+ micCode: 'XNGS'
128
+ })
129
+ ```
130
+
131
+ ### Error Handling
132
+
133
+ ```typescript
134
+ import { searchByISIN, OpenFigiError, RateLimitError, ValidationError } from 'openfigi-sdk'
135
+
136
+ try {
137
+ const response = await searchByISIN('invalid-isin')
138
+ } catch (error) {
139
+ if (error instanceof RateLimitError) {
140
+ console.log('Rate limited. Retry after:', error.retryAfter)
141
+ } else if (error instanceof ValidationError) {
142
+ console.log('Invalid request:', error.message)
143
+ } else if (error instanceof OpenFigiError) {
144
+ console.log('API error:', error.message, error.statusCode)
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### Rate Limit Information
150
+
151
+ ```typescript
152
+ import { searchByISIN, getRateLimitInfo } from 'openfigi-sdk'
153
+
154
+ // Check current rate limit status after any request
155
+ const response = await searchByISIN('US0378331005')
156
+ const rateLimitInfo = getRateLimitInfo()
157
+
158
+ if (rateLimitInfo) {
159
+ console.log('Rate limit:', rateLimitInfo.limit)
160
+ console.log('Remaining:', rateLimitInfo.remaining)
161
+ console.log('Reset time:', rateLimitInfo.reset)
162
+ }
163
+ ```
164
+
165
+ ## Supported Identifier Types
166
+
167
+ - `ID_ISIN` - International Securities Identification Number
168
+ - `ID_CUSIP` - Committee on Uniform Securities Identification Procedures
169
+ - `ID_SEDOL` - Stock Exchange Daily Official List
170
+ - `ID_BB_GLOBAL` - Bloomberg Global Identifier
171
+ - `ID_EXCH_SYMBOL` - Exchange symbol/ticker
172
+ - `ID_BB_UNIQUE` - Bloomberg Unique Identifier
173
+ - `ID_WERTPAPIER` - Wertpapierkennnummer (German securities code)
174
+ - And many more...
175
+
176
+ ## Development
177
+
178
+ ```bash
179
+ # Install dependencies
180
+ bun install
181
+
182
+ # Run tests
183
+ bun test
184
+
185
+ # Run tests with coverage
186
+ bun run test:coverage
187
+
188
+ # Build the library
189
+ bun run build
190
+
191
+ # Lint code
192
+ bun run lint
193
+
194
+ # Type check
195
+ bun run typecheck
196
+
197
+ # Generate documentation
198
+ bun run docs
199
+ ```
200
+
201
+ ## API Rate Limits
202
+
203
+ - **Without API Key**: Lower rate limit for public access
204
+ - **With API Key**: Higher rate limit for authenticated requests
205
+
206
+ To get an API key, sign up at [OpenFIGI.com](https://www.openfigi.com/).
207
+
208
+ ## Contributing
209
+
210
+ This is a **community-driven project** and contributions are welcome! Please feel free to submit a Pull Request.
211
+
212
+ 1. Fork the repository
213
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
214
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
215
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
216
+ 5. Open a Pull Request
217
+
218
+ **Note**: This library is maintained by the community and is not affiliated with OpenFIGI or Bloomberg. For official API support, please contact OpenFIGI directly.
219
+
220
+ ## License
221
+
222
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
223
+
224
+ ## Links
225
+
226
+ - [OpenFIGI API Documentation](https://www.openfigi.com/api/documentation)
227
+ - [OpenFIGI Website](https://www.openfigi.com/)
228
+ - [GitHub Repository](https://github.com/viktorlarsson/openfigi)
229
+ - [npm Package](https://www.npmjs.com/package/openfigi-sdk)
230
+
231
+ ## Acknowledgments
232
+
233
+ Built with modern tools and technologies:
234
+ - [Bun](https://bun.sh/) - Fast all-in-one JavaScript runtime
235
+ - [TypeScript](https://www.typescriptlang.org/) - Type-safe JavaScript
236
+ - [Vitest](https://vitest.dev/) - Fast unit testing framework
237
+ - [Biome](https://biomejs.dev/) - Fast formatter and linter
238
+ - [tsup](https://tsup.egoist.dev/) - Zero-config TypeScript bundler
239
+ - [Zod](https://zod.dev/) - TypeScript-first validation
package/dist/index.cjs ADDED
@@ -0,0 +1,434 @@
1
+ 'use strict';
2
+
3
+ var ky = require('ky');
4
+ var zod = require('zod');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var ky__default = /*#__PURE__*/_interopDefault(ky);
9
+
10
+ // src/client/client.ts
11
+
12
+ // src/utils/errors.ts
13
+ var OpenFigiError = class extends Error {
14
+ constructor(message, statusCode, response) {
15
+ super(message);
16
+ this.statusCode = statusCode;
17
+ this.response = response;
18
+ this.name = "OpenFigiError";
19
+ }
20
+ };
21
+ var RateLimitError = class extends OpenFigiError {
22
+ constructor(message, retryAfter, statusCode) {
23
+ super(message, statusCode);
24
+ this.retryAfter = retryAfter;
25
+ this.name = "RateLimitError";
26
+ }
27
+ };
28
+ var ValidationError = class extends OpenFigiError {
29
+ constructor(message, errors) {
30
+ super(message);
31
+ this.errors = errors;
32
+ this.name = "ValidationError";
33
+ }
34
+ };
35
+
36
+ // src/utils/helpers.ts
37
+ function sleep(ms) {
38
+ return new Promise((resolve) => setTimeout(resolve, ms));
39
+ }
40
+ function parseRateLimitHeaders(headers) {
41
+ const limit = headers.get("x-ratelimit-limit");
42
+ const remaining = headers.get("x-ratelimit-remaining");
43
+ const reset = headers.get("x-ratelimit-reset");
44
+ return {
45
+ limit: limit ? parseInt(limit, 10) : void 0,
46
+ remaining: remaining ? parseInt(remaining, 10) : void 0,
47
+ reset: reset ? new Date(parseInt(reset, 10) * 1e3) : void 0
48
+ };
49
+ }
50
+ function exponentialBackoff(attempt, baseDelay = 1e3, maxDelay = 3e4) {
51
+ const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
52
+ const jitter = Math.random() * 0.1 * delay;
53
+ return Math.floor(delay + jitter);
54
+ }
55
+ var IdTypeSchema = zod.z.enum([
56
+ "ID_ISIN",
57
+ "ID_BB_UNIQUE",
58
+ "ID_SEDOL",
59
+ "ID_COMMON",
60
+ "ID_WERTPAPIER",
61
+ "ID_CUSIP",
62
+ "ID_BB",
63
+ "ID_ITALY",
64
+ "ID_EXCH_SYMBOL",
65
+ "ID_FULL_EXCHANGE_SYMBOL",
66
+ "COMPOSITE_ID_BB_GLOBAL",
67
+ "ID_BB_GLOBAL_SHARE_CLASS_LEVEL",
68
+ "ID_BB_GLOBAL",
69
+ "ID_BB_SEC_NUM_DES",
70
+ "ID_BB_SEC_NUM",
71
+ "ID_CINS",
72
+ "ID_BELGIUM",
73
+ "ID_DENMARK",
74
+ "ID_FRANCE",
75
+ "ID_JAPAN",
76
+ "ID_LUXEMBOURG",
77
+ "ID_NETHERLANDS",
78
+ "ID_POLAND",
79
+ "ID_PORTUGAL",
80
+ "ID_SWEDEN",
81
+ "ID_SHORT_CODE"
82
+ ]);
83
+ var SecurityTypeSchema = zod.z.enum([
84
+ "Common Stock",
85
+ "Preference",
86
+ "ADR",
87
+ "Open-End Fund",
88
+ "Closed-End Fund",
89
+ "ETF",
90
+ "ETN",
91
+ "Unit",
92
+ "Mutual Fund",
93
+ "Money Market",
94
+ "Commodity",
95
+ "Currency",
96
+ "Option",
97
+ "Index"
98
+ ]);
99
+ var MarketSectorSchema = zod.z.enum([
100
+ "All",
101
+ "Comdty",
102
+ "Curncy",
103
+ "Equity",
104
+ "Govt",
105
+ "Corp",
106
+ "Index",
107
+ "Money",
108
+ "Mtge",
109
+ "Muni",
110
+ "Pref"
111
+ ]);
112
+ var MappingRequestSchema = zod.z.object({
113
+ idType: IdTypeSchema,
114
+ idValue: zod.z.string().min(1),
115
+ exchCode: zod.z.string().optional(),
116
+ micCode: zod.z.string().optional(),
117
+ currency: zod.z.string().length(3).optional(),
118
+ marketSecDes: MarketSectorSchema.optional(),
119
+ securityType: SecurityTypeSchema.optional(),
120
+ securityType2: zod.z.string().optional(),
121
+ includeUnlistedEquities: zod.z.boolean().optional(),
122
+ optionType: zod.z.enum(["Put", "Call"]).optional(),
123
+ strike: zod.z.array(zod.z.number()).optional(),
124
+ contractSize: zod.z.number().optional(),
125
+ coupon: zod.z.array(zod.z.number()).optional(),
126
+ expiration: zod.z.array(zod.z.number()).optional(),
127
+ maturity: zod.z.array(zod.z.number()).optional(),
128
+ stateCode: zod.z.string().length(2).optional()
129
+ });
130
+ var FigiResultSchema = zod.z.object({
131
+ figi: zod.z.string(),
132
+ securityType: SecurityTypeSchema.optional(),
133
+ marketSector: MarketSectorSchema.optional(),
134
+ ticker: zod.z.string().optional(),
135
+ name: zod.z.string().optional(),
136
+ exchCode: zod.z.string().optional(),
137
+ shareClassFIGI: zod.z.string().optional(),
138
+ compositeFIGI: zod.z.string().optional(),
139
+ securityType2: zod.z.string().optional(),
140
+ securityDescription: zod.z.string().optional(),
141
+ metadata: zod.z.string().optional()
142
+ });
143
+ var MappingResponseSchema = zod.z.object({
144
+ data: zod.z.array(FigiResultSchema).optional(),
145
+ warning: zod.z.string().optional(),
146
+ error: zod.z.string().optional()
147
+ });
148
+ zod.z.object({
149
+ error: zod.z.string(),
150
+ message: zod.z.string().optional(),
151
+ statusCode: zod.z.number().optional()
152
+ });
153
+ var ClientConfigSchema = zod.z.object({
154
+ apiKey: zod.z.string().optional(),
155
+ baseUrl: zod.z.string().url().optional(),
156
+ timeout: zod.z.number().positive().optional(),
157
+ retryLimit: zod.z.number().min(0).max(10).optional(),
158
+ retryDelay: zod.z.number().positive().optional(),
159
+ userAgent: zod.z.string().optional()
160
+ });
161
+
162
+ // src/client/client.ts
163
+ var DEFAULT_CONFIG = {
164
+ apiKey: "",
165
+ baseUrl: "https://api.openfigi.com",
166
+ timeout: 3e4,
167
+ retryLimit: 3,
168
+ retryDelay: 1e3,
169
+ userAgent: "@openfigi/sdk"
170
+ };
171
+ var currentRateLimitInfo;
172
+ var debugMode = false;
173
+ var setDebugMode = (enabled) => {
174
+ debugMode = enabled;
175
+ };
176
+ var log = (level, message, ...args) => {
177
+ if (!debugMode) return;
178
+ const prefix = `[@openfigi/sdk] [${level.toUpperCase()}]`;
179
+ console[level](prefix, message, ...args);
180
+ };
181
+ var createHttpClient = (config) => {
182
+ return ky__default.default.create({
183
+ prefixUrl: config.baseUrl,
184
+ timeout: config.timeout,
185
+ headers: {
186
+ "Content-Type": "application/json",
187
+ "User-Agent": config.userAgent,
188
+ ...config.apiKey && { "X-OPENFIGI-APIKEY": config.apiKey }
189
+ },
190
+ retry: {
191
+ limit: config.retryLimit,
192
+ methods: ["get", "post"],
193
+ statusCodes: [408, 413, 429, 500, 502, 503, 504]
194
+ },
195
+ hooks: {
196
+ beforeRequest: [
197
+ (request) => {
198
+ log("info", `Request: ${request.method} ${request.url}`);
199
+ }
200
+ ],
201
+ beforeRetry: [
202
+ async ({ error, retryCount }) => {
203
+ const delay = exponentialBackoff(retryCount, config.retryDelay);
204
+ log("warn", `Retry attempt ${retryCount} after ${delay}ms`, error.message);
205
+ await sleep(delay);
206
+ }
207
+ ],
208
+ afterResponse: [
209
+ (_request, _options, response) => {
210
+ const { limit, remaining, reset } = parseRateLimitHeaders(response.headers);
211
+ if (limit !== void 0 && remaining !== void 0 && reset) {
212
+ currentRateLimitInfo = { limit, remaining, reset };
213
+ log("info", `Rate limit: ${remaining}/${limit} (resets: ${reset.toISOString()})`);
214
+ }
215
+ log("info", `Response: ${response.status} ${response.statusText}`);
216
+ return response;
217
+ }
218
+ ]
219
+ }
220
+ });
221
+ };
222
+ var createClient = (config = {}) => {
223
+ const validation = ClientConfigSchema.safeParse(config);
224
+ if (!validation.success) {
225
+ const errors = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
226
+ throw new ValidationError(`Invalid client configuration: ${errors}`, validation.error);
227
+ }
228
+ const finalConfig = { ...DEFAULT_CONFIG, ...config };
229
+ const httpClient = createHttpClient(finalConfig);
230
+ const mapping2 = async (requests) => {
231
+ if (!Array.isArray(requests) || requests.length === 0) {
232
+ throw new ValidationError(
233
+ "Requests must be a non-empty array. Provide at least one mapping request."
234
+ );
235
+ }
236
+ if (requests.length > 100) {
237
+ throw new ValidationError(
238
+ `Too many requests: ${requests.length}. Maximum 100 requests allowed per call. Split into multiple batches.`
239
+ );
240
+ }
241
+ const validatedRequests = requests.map((req, index) => {
242
+ const validation2 = MappingRequestSchema.safeParse(req);
243
+ if (!validation2.success) {
244
+ const errors = validation2.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
245
+ throw new ValidationError(
246
+ `Invalid mapping request at index ${index}: ${errors}`,
247
+ validation2.error
248
+ );
249
+ }
250
+ return validation2.data;
251
+ });
252
+ try {
253
+ log("info", `Mapping ${validatedRequests.length} identifier(s)`);
254
+ const response = await httpClient.post("v3/mapping", {
255
+ json: validatedRequests
256
+ });
257
+ const data = await response.json();
258
+ if (!Array.isArray(data)) {
259
+ throw new OpenFigiError(
260
+ `Invalid API response: expected array but got ${typeof data}`,
261
+ response.status,
262
+ data
263
+ );
264
+ }
265
+ const validatedResponses = data.map((item, index) => {
266
+ const validation2 = MappingResponseSchema.safeParse(item);
267
+ if (!validation2.success) {
268
+ log("warn", `Invalid response at index ${index}:`, item, validation2.error);
269
+ return item;
270
+ }
271
+ return validation2.data;
272
+ });
273
+ log("info", `Mapped ${validatedResponses.length} identifier(s) successfully`);
274
+ return validatedResponses;
275
+ } catch (error) {
276
+ if (error instanceof OpenFigiError) {
277
+ throw error;
278
+ }
279
+ if (error instanceof Error && "response" in error) {
280
+ const httpError = error;
281
+ const status = httpError.response?.status;
282
+ if (status === 429) {
283
+ const retryAfter = httpError.response?.headers?.get("retry-after");
284
+ throw new RateLimitError(
285
+ "Rate limit exceeded. Please wait before making more requests.",
286
+ retryAfter ? parseInt(retryAfter, 10) : void 0,
287
+ status
288
+ );
289
+ }
290
+ if (status === 400) {
291
+ const body = await httpError.response?.text();
292
+ throw new ValidationError(`Bad request: ${body || "Invalid request format"}`);
293
+ }
294
+ if (status === 401) {
295
+ throw new OpenFigiError("Authentication failed. Check your API key.", status);
296
+ }
297
+ if (status === 404) {
298
+ throw new OpenFigiError("Endpoint not found. Please check the API version.", status);
299
+ }
300
+ throw new OpenFigiError(
301
+ `Request failed with status ${status}: ${httpError.message}`,
302
+ status,
303
+ await httpError.response?.text()
304
+ );
305
+ }
306
+ throw new OpenFigiError("Unexpected error occurred", void 0, error);
307
+ }
308
+ };
309
+ const mappingSingle2 = async (request) => {
310
+ const responses = await mapping2([request]);
311
+ return responses[0];
312
+ };
313
+ const searchByISIN2 = async (isin, options) => {
314
+ if (!isin || typeof isin !== "string") {
315
+ throw new ValidationError("ISIN must be a non-empty string");
316
+ }
317
+ return mappingSingle2({
318
+ idType: "ID_ISIN",
319
+ idValue: isin.trim(),
320
+ ...options
321
+ });
322
+ };
323
+ const searchByCUSIP2 = async (cusip, options) => {
324
+ if (!cusip || typeof cusip !== "string") {
325
+ throw new ValidationError("CUSIP must be a non-empty string");
326
+ }
327
+ return mappingSingle2({
328
+ idType: "ID_CUSIP",
329
+ idValue: cusip.trim(),
330
+ ...options
331
+ });
332
+ };
333
+ const searchBySEDOL2 = async (sedol, options) => {
334
+ if (!sedol || typeof sedol !== "string") {
335
+ throw new ValidationError("SEDOL must be a non-empty string");
336
+ }
337
+ return mappingSingle2({
338
+ idType: "ID_SEDOL",
339
+ idValue: sedol.trim(),
340
+ ...options
341
+ });
342
+ };
343
+ const searchByTicker2 = async (ticker, exchCode, options) => {
344
+ if (!ticker || typeof ticker !== "string") {
345
+ throw new ValidationError("Ticker must be a non-empty string");
346
+ }
347
+ return mappingSingle2({
348
+ idType: "ID_EXCH_SYMBOL",
349
+ idValue: ticker.trim().toUpperCase(),
350
+ exchCode: exchCode?.trim(),
351
+ ...options
352
+ });
353
+ };
354
+ const searchByBloombergId2 = async (bbgId, options) => {
355
+ if (!bbgId || typeof bbgId !== "string") {
356
+ throw new ValidationError("Bloomberg ID must be a non-empty string");
357
+ }
358
+ return mappingSingle2({
359
+ idType: "ID_BB_GLOBAL",
360
+ idValue: bbgId.trim(),
361
+ ...options
362
+ });
363
+ };
364
+ const getRateLimitInfo2 = () => {
365
+ return currentRateLimitInfo;
366
+ };
367
+ return {
368
+ mapping: mapping2,
369
+ mappingSingle: mappingSingle2,
370
+ searchByISIN: searchByISIN2,
371
+ searchByCUSIP: searchByCUSIP2,
372
+ searchBySEDOL: searchBySEDOL2,
373
+ searchByTicker: searchByTicker2,
374
+ searchByBloombergId: searchByBloombergId2,
375
+ getRateLimitInfo: getRateLimitInfo2
376
+ };
377
+ };
378
+ var defaultClient = createClient();
379
+ var mapping = defaultClient.mapping;
380
+ var mappingSingle = defaultClient.mappingSingle;
381
+ var searchByISIN = defaultClient.searchByISIN;
382
+ var searchByCUSIP = defaultClient.searchByCUSIP;
383
+ var searchBySEDOL = defaultClient.searchBySEDOL;
384
+ var searchByTicker = defaultClient.searchByTicker;
385
+ var searchByBloombergId = defaultClient.searchByBloombergId;
386
+ var getRateLimitInfo = defaultClient.getRateLimitInfo;
387
+
388
+ // src/utils/validators.ts
389
+ var isValidISIN = (isin) => {
390
+ return /^[A-Z]{2}[A-Z0-9]{9}[0-9]$/.test(isin);
391
+ };
392
+ var isValidCUSIP = (cusip) => {
393
+ return /^[A-Z0-9]{9}$/.test(cusip);
394
+ };
395
+ var isValidSEDOL = (sedol) => {
396
+ return /^[A-Z0-9]{7}$/.test(sedol);
397
+ };
398
+ var isValidBloombergId = (bbgId) => {
399
+ return /^BBG[A-Z0-9]{9}$/.test(bbgId);
400
+ };
401
+ var batchArray = (array, batchSize) => {
402
+ const batches = [];
403
+ for (let i = 0; i < array.length; i += batchSize) {
404
+ batches.push(array.slice(i, i + batchSize));
405
+ }
406
+ return batches;
407
+ };
408
+
409
+ exports.FigiResultSchema = FigiResultSchema;
410
+ exports.IdTypeSchema = IdTypeSchema;
411
+ exports.MappingRequestSchema = MappingRequestSchema;
412
+ exports.MappingResponseSchema = MappingResponseSchema;
413
+ exports.MarketSectorSchema = MarketSectorSchema;
414
+ exports.OpenFigiError = OpenFigiError;
415
+ exports.RateLimitError = RateLimitError;
416
+ exports.SecurityTypeSchema = SecurityTypeSchema;
417
+ exports.ValidationError = ValidationError;
418
+ exports.batchArray = batchArray;
419
+ exports.createClient = createClient;
420
+ exports.getRateLimitInfo = getRateLimitInfo;
421
+ exports.isValidBloombergId = isValidBloombergId;
422
+ exports.isValidCUSIP = isValidCUSIP;
423
+ exports.isValidISIN = isValidISIN;
424
+ exports.isValidSEDOL = isValidSEDOL;
425
+ exports.mapping = mapping;
426
+ exports.mappingSingle = mappingSingle;
427
+ exports.searchByBloombergId = searchByBloombergId;
428
+ exports.searchByCUSIP = searchByCUSIP;
429
+ exports.searchByISIN = searchByISIN;
430
+ exports.searchBySEDOL = searchBySEDOL;
431
+ exports.searchByTicker = searchByTicker;
432
+ exports.setDebugMode = setDebugMode;
433
+ //# sourceMappingURL=index.cjs.map
434
+ //# sourceMappingURL=index.cjs.map