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 +19 -0
- package/README.md +239 -0
- package/dist/index.cjs +434 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +352 -0
- package/dist/index.d.ts +352 -0
- package/dist/index.js +405 -0
- package/dist/index.js.map +1 -0
- package/package.json +79 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import ky from 'ky';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// src/client/client.ts
|
|
5
|
+
|
|
6
|
+
// src/utils/errors.ts
|
|
7
|
+
var OpenFigiError = class extends Error {
|
|
8
|
+
constructor(message, statusCode, response) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
this.response = response;
|
|
12
|
+
this.name = "OpenFigiError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var RateLimitError = class extends OpenFigiError {
|
|
16
|
+
constructor(message, retryAfter, statusCode) {
|
|
17
|
+
super(message, statusCode);
|
|
18
|
+
this.retryAfter = retryAfter;
|
|
19
|
+
this.name = "RateLimitError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var ValidationError = class extends OpenFigiError {
|
|
23
|
+
constructor(message, errors) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.errors = errors;
|
|
26
|
+
this.name = "ValidationError";
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/utils/helpers.ts
|
|
31
|
+
function sleep(ms) {
|
|
32
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
function parseRateLimitHeaders(headers) {
|
|
35
|
+
const limit = headers.get("x-ratelimit-limit");
|
|
36
|
+
const remaining = headers.get("x-ratelimit-remaining");
|
|
37
|
+
const reset = headers.get("x-ratelimit-reset");
|
|
38
|
+
return {
|
|
39
|
+
limit: limit ? parseInt(limit, 10) : void 0,
|
|
40
|
+
remaining: remaining ? parseInt(remaining, 10) : void 0,
|
|
41
|
+
reset: reset ? new Date(parseInt(reset, 10) * 1e3) : void 0
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function exponentialBackoff(attempt, baseDelay = 1e3, maxDelay = 3e4) {
|
|
45
|
+
const delay = Math.min(baseDelay * 2 ** attempt, maxDelay);
|
|
46
|
+
const jitter = Math.random() * 0.1 * delay;
|
|
47
|
+
return Math.floor(delay + jitter);
|
|
48
|
+
}
|
|
49
|
+
var IdTypeSchema = z.enum([
|
|
50
|
+
"ID_ISIN",
|
|
51
|
+
"ID_BB_UNIQUE",
|
|
52
|
+
"ID_SEDOL",
|
|
53
|
+
"ID_COMMON",
|
|
54
|
+
"ID_WERTPAPIER",
|
|
55
|
+
"ID_CUSIP",
|
|
56
|
+
"ID_BB",
|
|
57
|
+
"ID_ITALY",
|
|
58
|
+
"ID_EXCH_SYMBOL",
|
|
59
|
+
"ID_FULL_EXCHANGE_SYMBOL",
|
|
60
|
+
"COMPOSITE_ID_BB_GLOBAL",
|
|
61
|
+
"ID_BB_GLOBAL_SHARE_CLASS_LEVEL",
|
|
62
|
+
"ID_BB_GLOBAL",
|
|
63
|
+
"ID_BB_SEC_NUM_DES",
|
|
64
|
+
"ID_BB_SEC_NUM",
|
|
65
|
+
"ID_CINS",
|
|
66
|
+
"ID_BELGIUM",
|
|
67
|
+
"ID_DENMARK",
|
|
68
|
+
"ID_FRANCE",
|
|
69
|
+
"ID_JAPAN",
|
|
70
|
+
"ID_LUXEMBOURG",
|
|
71
|
+
"ID_NETHERLANDS",
|
|
72
|
+
"ID_POLAND",
|
|
73
|
+
"ID_PORTUGAL",
|
|
74
|
+
"ID_SWEDEN",
|
|
75
|
+
"ID_SHORT_CODE"
|
|
76
|
+
]);
|
|
77
|
+
var SecurityTypeSchema = z.enum([
|
|
78
|
+
"Common Stock",
|
|
79
|
+
"Preference",
|
|
80
|
+
"ADR",
|
|
81
|
+
"Open-End Fund",
|
|
82
|
+
"Closed-End Fund",
|
|
83
|
+
"ETF",
|
|
84
|
+
"ETN",
|
|
85
|
+
"Unit",
|
|
86
|
+
"Mutual Fund",
|
|
87
|
+
"Money Market",
|
|
88
|
+
"Commodity",
|
|
89
|
+
"Currency",
|
|
90
|
+
"Option",
|
|
91
|
+
"Index"
|
|
92
|
+
]);
|
|
93
|
+
var MarketSectorSchema = z.enum([
|
|
94
|
+
"All",
|
|
95
|
+
"Comdty",
|
|
96
|
+
"Curncy",
|
|
97
|
+
"Equity",
|
|
98
|
+
"Govt",
|
|
99
|
+
"Corp",
|
|
100
|
+
"Index",
|
|
101
|
+
"Money",
|
|
102
|
+
"Mtge",
|
|
103
|
+
"Muni",
|
|
104
|
+
"Pref"
|
|
105
|
+
]);
|
|
106
|
+
var MappingRequestSchema = z.object({
|
|
107
|
+
idType: IdTypeSchema,
|
|
108
|
+
idValue: z.string().min(1),
|
|
109
|
+
exchCode: z.string().optional(),
|
|
110
|
+
micCode: z.string().optional(),
|
|
111
|
+
currency: z.string().length(3).optional(),
|
|
112
|
+
marketSecDes: MarketSectorSchema.optional(),
|
|
113
|
+
securityType: SecurityTypeSchema.optional(),
|
|
114
|
+
securityType2: z.string().optional(),
|
|
115
|
+
includeUnlistedEquities: z.boolean().optional(),
|
|
116
|
+
optionType: z.enum(["Put", "Call"]).optional(),
|
|
117
|
+
strike: z.array(z.number()).optional(),
|
|
118
|
+
contractSize: z.number().optional(),
|
|
119
|
+
coupon: z.array(z.number()).optional(),
|
|
120
|
+
expiration: z.array(z.number()).optional(),
|
|
121
|
+
maturity: z.array(z.number()).optional(),
|
|
122
|
+
stateCode: z.string().length(2).optional()
|
|
123
|
+
});
|
|
124
|
+
var FigiResultSchema = z.object({
|
|
125
|
+
figi: z.string(),
|
|
126
|
+
securityType: SecurityTypeSchema.optional(),
|
|
127
|
+
marketSector: MarketSectorSchema.optional(),
|
|
128
|
+
ticker: z.string().optional(),
|
|
129
|
+
name: z.string().optional(),
|
|
130
|
+
exchCode: z.string().optional(),
|
|
131
|
+
shareClassFIGI: z.string().optional(),
|
|
132
|
+
compositeFIGI: z.string().optional(),
|
|
133
|
+
securityType2: z.string().optional(),
|
|
134
|
+
securityDescription: z.string().optional(),
|
|
135
|
+
metadata: z.string().optional()
|
|
136
|
+
});
|
|
137
|
+
var MappingResponseSchema = z.object({
|
|
138
|
+
data: z.array(FigiResultSchema).optional(),
|
|
139
|
+
warning: z.string().optional(),
|
|
140
|
+
error: z.string().optional()
|
|
141
|
+
});
|
|
142
|
+
z.object({
|
|
143
|
+
error: z.string(),
|
|
144
|
+
message: z.string().optional(),
|
|
145
|
+
statusCode: z.number().optional()
|
|
146
|
+
});
|
|
147
|
+
var ClientConfigSchema = z.object({
|
|
148
|
+
apiKey: z.string().optional(),
|
|
149
|
+
baseUrl: z.string().url().optional(),
|
|
150
|
+
timeout: z.number().positive().optional(),
|
|
151
|
+
retryLimit: z.number().min(0).max(10).optional(),
|
|
152
|
+
retryDelay: z.number().positive().optional(),
|
|
153
|
+
userAgent: z.string().optional()
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// src/client/client.ts
|
|
157
|
+
var DEFAULT_CONFIG = {
|
|
158
|
+
apiKey: "",
|
|
159
|
+
baseUrl: "https://api.openfigi.com",
|
|
160
|
+
timeout: 3e4,
|
|
161
|
+
retryLimit: 3,
|
|
162
|
+
retryDelay: 1e3,
|
|
163
|
+
userAgent: "@openfigi/sdk"
|
|
164
|
+
};
|
|
165
|
+
var currentRateLimitInfo;
|
|
166
|
+
var debugMode = false;
|
|
167
|
+
var setDebugMode = (enabled) => {
|
|
168
|
+
debugMode = enabled;
|
|
169
|
+
};
|
|
170
|
+
var log = (level, message, ...args) => {
|
|
171
|
+
if (!debugMode) return;
|
|
172
|
+
const prefix = `[@openfigi/sdk] [${level.toUpperCase()}]`;
|
|
173
|
+
console[level](prefix, message, ...args);
|
|
174
|
+
};
|
|
175
|
+
var createHttpClient = (config) => {
|
|
176
|
+
return ky.create({
|
|
177
|
+
prefixUrl: config.baseUrl,
|
|
178
|
+
timeout: config.timeout,
|
|
179
|
+
headers: {
|
|
180
|
+
"Content-Type": "application/json",
|
|
181
|
+
"User-Agent": config.userAgent,
|
|
182
|
+
...config.apiKey && { "X-OPENFIGI-APIKEY": config.apiKey }
|
|
183
|
+
},
|
|
184
|
+
retry: {
|
|
185
|
+
limit: config.retryLimit,
|
|
186
|
+
methods: ["get", "post"],
|
|
187
|
+
statusCodes: [408, 413, 429, 500, 502, 503, 504]
|
|
188
|
+
},
|
|
189
|
+
hooks: {
|
|
190
|
+
beforeRequest: [
|
|
191
|
+
(request) => {
|
|
192
|
+
log("info", `Request: ${request.method} ${request.url}`);
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
beforeRetry: [
|
|
196
|
+
async ({ error, retryCount }) => {
|
|
197
|
+
const delay = exponentialBackoff(retryCount, config.retryDelay);
|
|
198
|
+
log("warn", `Retry attempt ${retryCount} after ${delay}ms`, error.message);
|
|
199
|
+
await sleep(delay);
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
afterResponse: [
|
|
203
|
+
(_request, _options, response) => {
|
|
204
|
+
const { limit, remaining, reset } = parseRateLimitHeaders(response.headers);
|
|
205
|
+
if (limit !== void 0 && remaining !== void 0 && reset) {
|
|
206
|
+
currentRateLimitInfo = { limit, remaining, reset };
|
|
207
|
+
log("info", `Rate limit: ${remaining}/${limit} (resets: ${reset.toISOString()})`);
|
|
208
|
+
}
|
|
209
|
+
log("info", `Response: ${response.status} ${response.statusText}`);
|
|
210
|
+
return response;
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
var createClient = (config = {}) => {
|
|
217
|
+
const validation = ClientConfigSchema.safeParse(config);
|
|
218
|
+
if (!validation.success) {
|
|
219
|
+
const errors = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
220
|
+
throw new ValidationError(`Invalid client configuration: ${errors}`, validation.error);
|
|
221
|
+
}
|
|
222
|
+
const finalConfig = { ...DEFAULT_CONFIG, ...config };
|
|
223
|
+
const httpClient = createHttpClient(finalConfig);
|
|
224
|
+
const mapping2 = async (requests) => {
|
|
225
|
+
if (!Array.isArray(requests) || requests.length === 0) {
|
|
226
|
+
throw new ValidationError(
|
|
227
|
+
"Requests must be a non-empty array. Provide at least one mapping request."
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
if (requests.length > 100) {
|
|
231
|
+
throw new ValidationError(
|
|
232
|
+
`Too many requests: ${requests.length}. Maximum 100 requests allowed per call. Split into multiple batches.`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
const validatedRequests = requests.map((req, index) => {
|
|
236
|
+
const validation2 = MappingRequestSchema.safeParse(req);
|
|
237
|
+
if (!validation2.success) {
|
|
238
|
+
const errors = validation2.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
239
|
+
throw new ValidationError(
|
|
240
|
+
`Invalid mapping request at index ${index}: ${errors}`,
|
|
241
|
+
validation2.error
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return validation2.data;
|
|
245
|
+
});
|
|
246
|
+
try {
|
|
247
|
+
log("info", `Mapping ${validatedRequests.length} identifier(s)`);
|
|
248
|
+
const response = await httpClient.post("v3/mapping", {
|
|
249
|
+
json: validatedRequests
|
|
250
|
+
});
|
|
251
|
+
const data = await response.json();
|
|
252
|
+
if (!Array.isArray(data)) {
|
|
253
|
+
throw new OpenFigiError(
|
|
254
|
+
`Invalid API response: expected array but got ${typeof data}`,
|
|
255
|
+
response.status,
|
|
256
|
+
data
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
const validatedResponses = data.map((item, index) => {
|
|
260
|
+
const validation2 = MappingResponseSchema.safeParse(item);
|
|
261
|
+
if (!validation2.success) {
|
|
262
|
+
log("warn", `Invalid response at index ${index}:`, item, validation2.error);
|
|
263
|
+
return item;
|
|
264
|
+
}
|
|
265
|
+
return validation2.data;
|
|
266
|
+
});
|
|
267
|
+
log("info", `Mapped ${validatedResponses.length} identifier(s) successfully`);
|
|
268
|
+
return validatedResponses;
|
|
269
|
+
} catch (error) {
|
|
270
|
+
if (error instanceof OpenFigiError) {
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
if (error instanceof Error && "response" in error) {
|
|
274
|
+
const httpError = error;
|
|
275
|
+
const status = httpError.response?.status;
|
|
276
|
+
if (status === 429) {
|
|
277
|
+
const retryAfter = httpError.response?.headers?.get("retry-after");
|
|
278
|
+
throw new RateLimitError(
|
|
279
|
+
"Rate limit exceeded. Please wait before making more requests.",
|
|
280
|
+
retryAfter ? parseInt(retryAfter, 10) : void 0,
|
|
281
|
+
status
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
if (status === 400) {
|
|
285
|
+
const body = await httpError.response?.text();
|
|
286
|
+
throw new ValidationError(`Bad request: ${body || "Invalid request format"}`);
|
|
287
|
+
}
|
|
288
|
+
if (status === 401) {
|
|
289
|
+
throw new OpenFigiError("Authentication failed. Check your API key.", status);
|
|
290
|
+
}
|
|
291
|
+
if (status === 404) {
|
|
292
|
+
throw new OpenFigiError("Endpoint not found. Please check the API version.", status);
|
|
293
|
+
}
|
|
294
|
+
throw new OpenFigiError(
|
|
295
|
+
`Request failed with status ${status}: ${httpError.message}`,
|
|
296
|
+
status,
|
|
297
|
+
await httpError.response?.text()
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
throw new OpenFigiError("Unexpected error occurred", void 0, error);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
const mappingSingle2 = async (request) => {
|
|
304
|
+
const responses = await mapping2([request]);
|
|
305
|
+
return responses[0];
|
|
306
|
+
};
|
|
307
|
+
const searchByISIN2 = async (isin, options) => {
|
|
308
|
+
if (!isin || typeof isin !== "string") {
|
|
309
|
+
throw new ValidationError("ISIN must be a non-empty string");
|
|
310
|
+
}
|
|
311
|
+
return mappingSingle2({
|
|
312
|
+
idType: "ID_ISIN",
|
|
313
|
+
idValue: isin.trim(),
|
|
314
|
+
...options
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
const searchByCUSIP2 = async (cusip, options) => {
|
|
318
|
+
if (!cusip || typeof cusip !== "string") {
|
|
319
|
+
throw new ValidationError("CUSIP must be a non-empty string");
|
|
320
|
+
}
|
|
321
|
+
return mappingSingle2({
|
|
322
|
+
idType: "ID_CUSIP",
|
|
323
|
+
idValue: cusip.trim(),
|
|
324
|
+
...options
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
const searchBySEDOL2 = async (sedol, options) => {
|
|
328
|
+
if (!sedol || typeof sedol !== "string") {
|
|
329
|
+
throw new ValidationError("SEDOL must be a non-empty string");
|
|
330
|
+
}
|
|
331
|
+
return mappingSingle2({
|
|
332
|
+
idType: "ID_SEDOL",
|
|
333
|
+
idValue: sedol.trim(),
|
|
334
|
+
...options
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
const searchByTicker2 = async (ticker, exchCode, options) => {
|
|
338
|
+
if (!ticker || typeof ticker !== "string") {
|
|
339
|
+
throw new ValidationError("Ticker must be a non-empty string");
|
|
340
|
+
}
|
|
341
|
+
return mappingSingle2({
|
|
342
|
+
idType: "ID_EXCH_SYMBOL",
|
|
343
|
+
idValue: ticker.trim().toUpperCase(),
|
|
344
|
+
exchCode: exchCode?.trim(),
|
|
345
|
+
...options
|
|
346
|
+
});
|
|
347
|
+
};
|
|
348
|
+
const searchByBloombergId2 = async (bbgId, options) => {
|
|
349
|
+
if (!bbgId || typeof bbgId !== "string") {
|
|
350
|
+
throw new ValidationError("Bloomberg ID must be a non-empty string");
|
|
351
|
+
}
|
|
352
|
+
return mappingSingle2({
|
|
353
|
+
idType: "ID_BB_GLOBAL",
|
|
354
|
+
idValue: bbgId.trim(),
|
|
355
|
+
...options
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
const getRateLimitInfo2 = () => {
|
|
359
|
+
return currentRateLimitInfo;
|
|
360
|
+
};
|
|
361
|
+
return {
|
|
362
|
+
mapping: mapping2,
|
|
363
|
+
mappingSingle: mappingSingle2,
|
|
364
|
+
searchByISIN: searchByISIN2,
|
|
365
|
+
searchByCUSIP: searchByCUSIP2,
|
|
366
|
+
searchBySEDOL: searchBySEDOL2,
|
|
367
|
+
searchByTicker: searchByTicker2,
|
|
368
|
+
searchByBloombergId: searchByBloombergId2,
|
|
369
|
+
getRateLimitInfo: getRateLimitInfo2
|
|
370
|
+
};
|
|
371
|
+
};
|
|
372
|
+
var defaultClient = createClient();
|
|
373
|
+
var mapping = defaultClient.mapping;
|
|
374
|
+
var mappingSingle = defaultClient.mappingSingle;
|
|
375
|
+
var searchByISIN = defaultClient.searchByISIN;
|
|
376
|
+
var searchByCUSIP = defaultClient.searchByCUSIP;
|
|
377
|
+
var searchBySEDOL = defaultClient.searchBySEDOL;
|
|
378
|
+
var searchByTicker = defaultClient.searchByTicker;
|
|
379
|
+
var searchByBloombergId = defaultClient.searchByBloombergId;
|
|
380
|
+
var getRateLimitInfo = defaultClient.getRateLimitInfo;
|
|
381
|
+
|
|
382
|
+
// src/utils/validators.ts
|
|
383
|
+
var isValidISIN = (isin) => {
|
|
384
|
+
return /^[A-Z]{2}[A-Z0-9]{9}[0-9]$/.test(isin);
|
|
385
|
+
};
|
|
386
|
+
var isValidCUSIP = (cusip) => {
|
|
387
|
+
return /^[A-Z0-9]{9}$/.test(cusip);
|
|
388
|
+
};
|
|
389
|
+
var isValidSEDOL = (sedol) => {
|
|
390
|
+
return /^[A-Z0-9]{7}$/.test(sedol);
|
|
391
|
+
};
|
|
392
|
+
var isValidBloombergId = (bbgId) => {
|
|
393
|
+
return /^BBG[A-Z0-9]{9}$/.test(bbgId);
|
|
394
|
+
};
|
|
395
|
+
var batchArray = (array, batchSize) => {
|
|
396
|
+
const batches = [];
|
|
397
|
+
for (let i = 0; i < array.length; i += batchSize) {
|
|
398
|
+
batches.push(array.slice(i, i + batchSize));
|
|
399
|
+
}
|
|
400
|
+
return batches;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
export { FigiResultSchema, IdTypeSchema, MappingRequestSchema, MappingResponseSchema, MarketSectorSchema, OpenFigiError, RateLimitError, SecurityTypeSchema, ValidationError, batchArray, createClient, getRateLimitInfo, isValidBloombergId, isValidCUSIP, isValidISIN, isValidSEDOL, mapping, mappingSingle, searchByBloombergId, searchByCUSIP, searchByISIN, searchBySEDOL, searchByTicker, setDebugMode };
|
|
404
|
+
//# sourceMappingURL=index.js.map
|
|
405
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/errors.ts","../src/utils/helpers.ts","../src/validators/index.ts","../src/client/client.ts","../src/utils/validators.ts"],"names":["mapping","validation","mappingSingle","searchByISIN","searchByCUSIP","searchBySEDOL","searchByTicker","searchByBloombergId","getRateLimitInfo"],"mappings":"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","file":"index.js","sourcesContent":["export class OpenFigiError extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public response?: unknown\n ) {\n super(message)\n this.name = 'OpenFigiError'\n }\n}\n\nexport class RateLimitError extends OpenFigiError {\n constructor(\n message: string,\n public retryAfter?: number,\n statusCode?: number\n ) {\n super(message, statusCode)\n this.name = 'RateLimitError'\n }\n}\n\nexport class ValidationError extends OpenFigiError {\n constructor(\n message: string,\n public errors?: unknown\n ) {\n super(message)\n this.name = 'ValidationError'\n }\n}\n","export function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nexport function parseRateLimitHeaders(headers: Headers): {\n limit?: number\n remaining?: number\n reset?: Date\n} {\n const limit = headers.get('x-ratelimit-limit')\n const remaining = headers.get('x-ratelimit-remaining')\n const reset = headers.get('x-ratelimit-reset')\n\n return {\n limit: limit ? parseInt(limit, 10) : undefined,\n remaining: remaining ? parseInt(remaining, 10) : undefined,\n reset: reset ? new Date(parseInt(reset, 10) * 1000) : undefined,\n }\n}\n\nexport function exponentialBackoff(\n attempt: number,\n baseDelay: number = 1000,\n maxDelay: number = 30000\n): number {\n const delay = Math.min(baseDelay * 2 ** attempt, maxDelay)\n const jitter = Math.random() * 0.1 * delay\n return Math.floor(delay + jitter)\n}\n","import { z } from 'zod'\n\nexport const IdTypeSchema = z.enum([\n 'ID_ISIN',\n 'ID_BB_UNIQUE',\n 'ID_SEDOL',\n 'ID_COMMON',\n 'ID_WERTPAPIER',\n 'ID_CUSIP',\n 'ID_BB',\n 'ID_ITALY',\n 'ID_EXCH_SYMBOL',\n 'ID_FULL_EXCHANGE_SYMBOL',\n 'COMPOSITE_ID_BB_GLOBAL',\n 'ID_BB_GLOBAL_SHARE_CLASS_LEVEL',\n 'ID_BB_GLOBAL',\n 'ID_BB_SEC_NUM_DES',\n 'ID_BB_SEC_NUM',\n 'ID_CINS',\n 'ID_BELGIUM',\n 'ID_DENMARK',\n 'ID_FRANCE',\n 'ID_JAPAN',\n 'ID_LUXEMBOURG',\n 'ID_NETHERLANDS',\n 'ID_POLAND',\n 'ID_PORTUGAL',\n 'ID_SWEDEN',\n 'ID_SHORT_CODE',\n])\n\nexport const SecurityTypeSchema = z.enum([\n 'Common Stock',\n 'Preference',\n 'ADR',\n 'Open-End Fund',\n 'Closed-End Fund',\n 'ETF',\n 'ETN',\n 'Unit',\n 'Mutual Fund',\n 'Money Market',\n 'Commodity',\n 'Currency',\n 'Option',\n 'Index',\n])\n\nexport const MarketSectorSchema = z.enum([\n 'All',\n 'Comdty',\n 'Curncy',\n 'Equity',\n 'Govt',\n 'Corp',\n 'Index',\n 'Money',\n 'Mtge',\n 'Muni',\n 'Pref',\n])\n\nexport const MappingRequestSchema = z.object({\n idType: IdTypeSchema,\n idValue: z.string().min(1),\n exchCode: z.string().optional(),\n micCode: z.string().optional(),\n currency: z.string().length(3).optional(),\n marketSecDes: MarketSectorSchema.optional(),\n securityType: SecurityTypeSchema.optional(),\n securityType2: z.string().optional(),\n includeUnlistedEquities: z.boolean().optional(),\n optionType: z.enum(['Put', 'Call']).optional(),\n strike: z.array(z.number()).optional(),\n contractSize: z.number().optional(),\n coupon: z.array(z.number()).optional(),\n expiration: z.array(z.number()).optional(),\n maturity: z.array(z.number()).optional(),\n stateCode: z.string().length(2).optional(),\n})\n\nexport const FigiResultSchema = z.object({\n figi: z.string(),\n securityType: SecurityTypeSchema.optional(),\n marketSector: MarketSectorSchema.optional(),\n ticker: z.string().optional(),\n name: z.string().optional(),\n exchCode: z.string().optional(),\n shareClassFIGI: z.string().optional(),\n compositeFIGI: z.string().optional(),\n securityType2: z.string().optional(),\n securityDescription: z.string().optional(),\n metadata: z.string().optional(),\n})\n\nexport const MappingResponseSchema = z.object({\n data: z.array(FigiResultSchema).optional(),\n warning: z.string().optional(),\n error: z.string().optional(),\n})\n\nexport const ApiErrorSchema = z.object({\n error: z.string(),\n message: z.string().optional(),\n statusCode: z.number().optional(),\n})\n\nexport const ClientConfigSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z.string().url().optional(),\n timeout: z.number().positive().optional(),\n retryLimit: z.number().min(0).max(10).optional(),\n retryDelay: z.number().positive().optional(),\n userAgent: z.string().optional(),\n})\n","import ky, { type HTTPError, type KyInstance } from 'ky'\nimport type { ClientConfig, MappingRequest, MappingResponse, RateLimitInfo } from '../types'\nimport { OpenFigiError, RateLimitError, ValidationError } from '../utils/errors'\nimport { exponentialBackoff, parseRateLimitHeaders, sleep } from '../utils/helpers'\nimport { ClientConfigSchema, MappingRequestSchema, MappingResponseSchema } from '../validators'\n\nconst DEFAULT_CONFIG: Required<ClientConfig> = {\n apiKey: '',\n baseUrl: 'https://api.openfigi.com',\n timeout: 30000,\n retryLimit: 3,\n retryDelay: 1000,\n userAgent: '@openfigi/sdk',\n}\n\nlet currentRateLimitInfo: RateLimitInfo | undefined\nlet debugMode = false\n\n/**\n * Enable or disable debug logging\n * @param enabled - Whether to enable debug mode\n */\nexport const setDebugMode = (enabled: boolean) => {\n debugMode = enabled\n}\n\nconst log = (level: 'info' | 'warn' | 'error', message: string, ...args: unknown[]) => {\n if (!debugMode) return\n const prefix = `[@openfigi/sdk] [${level.toUpperCase()}]`\n console[level](prefix, message, ...args)\n}\n\nconst createHttpClient = (config: Required<ClientConfig>): KyInstance => {\n return ky.create({\n prefixUrl: config.baseUrl,\n timeout: config.timeout,\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': config.userAgent,\n ...(config.apiKey && { 'X-OPENFIGI-APIKEY': config.apiKey }),\n },\n retry: {\n limit: config.retryLimit,\n methods: ['get', 'post'],\n statusCodes: [408, 413, 429, 500, 502, 503, 504],\n },\n hooks: {\n beforeRequest: [\n (request) => {\n log('info', `Request: ${request.method} ${request.url}`)\n },\n ],\n beforeRetry: [\n async ({ error, retryCount }) => {\n const delay = exponentialBackoff(retryCount, config.retryDelay)\n log('warn', `Retry attempt ${retryCount} after ${delay}ms`, error.message)\n await sleep(delay)\n },\n ],\n afterResponse: [\n (_request, _options, response) => {\n const { limit, remaining, reset } = parseRateLimitHeaders(response.headers)\n if (limit !== undefined && remaining !== undefined && reset) {\n currentRateLimitInfo = { limit, remaining, reset }\n log('info', `Rate limit: ${remaining}/${limit} (resets: ${reset.toISOString()})`)\n }\n log('info', `Response: ${response.status} ${response.statusText}`)\n return response\n },\n ],\n },\n })\n}\n\n/**\n * Creates an OpenFIGI client with custom configuration\n *\n * @param config - Client configuration options\n * @returns An OpenFIGI client instance with all available methods\n *\n * @example\n * ```typescript\n * const client = createClient({\n * apiKey: 'your-api-key',\n * timeout: 60000\n * })\n * ```\n */\nexport const createClient = (config: ClientConfig = {}) => {\n const validation = ClientConfigSchema.safeParse(config)\n if (!validation.success) {\n const errors = validation.error.issues\n .map((e) => `${e.path.join('.')}: ${e.message}`)\n .join(', ')\n throw new ValidationError(`Invalid client configuration: ${errors}`, validation.error)\n }\n\n const finalConfig = { ...DEFAULT_CONFIG, ...config }\n const httpClient = createHttpClient(finalConfig)\n\n /**\n * Map multiple identifiers to FIGIs in a single request\n *\n * @param requests - Array of mapping requests (max 100)\n * @returns Array of mapping responses in the same order as requests\n * @throws {ValidationError} If requests are invalid\n * @throws {RateLimitError} If rate limit is exceeded\n * @throws {OpenFigiError} If API returns an error\n *\n * @example\n * ```typescript\n * const responses = await mapping([\n * { idType: 'ID_ISIN', idValue: 'US0378331005' },\n * { idType: 'ID_CUSIP', idValue: '037833100' }\n * ])\n * ```\n */\n const mapping = async (requests: MappingRequest[]): Promise<MappingResponse[]> => {\n if (!Array.isArray(requests) || requests.length === 0) {\n throw new ValidationError(\n 'Requests must be a non-empty array. Provide at least one mapping request.'\n )\n }\n\n if (requests.length > 100) {\n throw new ValidationError(\n `Too many requests: ${requests.length}. Maximum 100 requests allowed per call. Split into multiple batches.`\n )\n }\n\n const validatedRequests = requests.map((req, index) => {\n const validation = MappingRequestSchema.safeParse(req)\n if (!validation.success) {\n const errors = validation.error.issues\n .map((e) => `${e.path.join('.')}: ${e.message}`)\n .join(', ')\n throw new ValidationError(\n `Invalid mapping request at index ${index}: ${errors}`,\n validation.error\n )\n }\n return validation.data\n })\n\n try {\n log('info', `Mapping ${validatedRequests.length} identifier(s)`)\n const response = await httpClient.post('v3/mapping', {\n json: validatedRequests,\n })\n\n const data = (await response.json()) as unknown\n\n if (!Array.isArray(data)) {\n throw new OpenFigiError(\n `Invalid API response: expected array but got ${typeof data}`,\n response.status,\n data\n )\n }\n\n const validatedResponses = data.map((item, index) => {\n const validation = MappingResponseSchema.safeParse(item)\n if (!validation.success) {\n log('warn', `Invalid response at index ${index}:`, item, validation.error)\n return item as MappingResponse\n }\n return validation.data\n })\n\n log('info', `Mapped ${validatedResponses.length} identifier(s) successfully`)\n return validatedResponses\n } catch (error) {\n if (error instanceof OpenFigiError) {\n throw error\n }\n\n if (error instanceof Error && 'response' in error) {\n const httpError = error as HTTPError\n const status = httpError.response?.status\n\n if (status === 429) {\n const retryAfter = httpError.response?.headers?.get('retry-after')\n throw new RateLimitError(\n 'Rate limit exceeded. Please wait before making more requests.',\n retryAfter ? parseInt(retryAfter, 10) : undefined,\n status\n )\n }\n\n if (status === 400) {\n const body = await httpError.response?.text()\n throw new ValidationError(`Bad request: ${body || 'Invalid request format'}`)\n }\n\n if (status === 401) {\n throw new OpenFigiError('Authentication failed. Check your API key.', status)\n }\n\n if (status === 404) {\n throw new OpenFigiError('Endpoint not found. Please check the API version.', status)\n }\n\n throw new OpenFigiError(\n `Request failed with status ${status}: ${httpError.message}`,\n status,\n await httpError.response?.text()\n )\n }\n\n throw new OpenFigiError('Unexpected error occurred', undefined, error)\n }\n }\n\n /**\n * Map a single identifier to FIGI\n *\n * @param request - Single mapping request\n * @returns Mapping response\n *\n * @example\n * ```typescript\n * const response = await mappingSingle({\n * idType: 'ID_ISIN',\n * idValue: 'US0378331005'\n * })\n * ```\n */\n const mappingSingle = async (request: MappingRequest): Promise<MappingResponse> => {\n const responses = await mapping([request])\n return responses[0]\n }\n\n /**\n * Search for FIGI by ISIN\n *\n * @param isin - ISIN identifier (e.g., 'US0378331005')\n * @param options - Additional search options\n * @returns Mapping response with FIGI data\n *\n * @example\n * ```typescript\n * const result = await searchByISIN('US0378331005')\n * if (result.data) {\n * console.log('FIGI:', result.data[0].figi)\n * }\n * ```\n */\n const searchByISIN = async (\n isin: string,\n options?: Partial<MappingRequest>\n ): Promise<MappingResponse> => {\n if (!isin || typeof isin !== 'string') {\n throw new ValidationError('ISIN must be a non-empty string')\n }\n return mappingSingle({\n idType: 'ID_ISIN',\n idValue: isin.trim(),\n ...options,\n })\n }\n\n /**\n * Search for FIGI by CUSIP\n *\n * @param cusip - CUSIP identifier (e.g., '037833100')\n * @param options - Additional search options\n * @returns Mapping response with FIGI data\n */\n const searchByCUSIP = async (\n cusip: string,\n options?: Partial<MappingRequest>\n ): Promise<MappingResponse> => {\n if (!cusip || typeof cusip !== 'string') {\n throw new ValidationError('CUSIP must be a non-empty string')\n }\n return mappingSingle({\n idType: 'ID_CUSIP',\n idValue: cusip.trim(),\n ...options,\n })\n }\n\n /**\n * Search for FIGI by SEDOL\n *\n * @param sedol - SEDOL identifier (e.g., '2046251')\n * @param options - Additional search options\n * @returns Mapping response with FIGI data\n */\n const searchBySEDOL = async (\n sedol: string,\n options?: Partial<MappingRequest>\n ): Promise<MappingResponse> => {\n if (!sedol || typeof sedol !== 'string') {\n throw new ValidationError('SEDOL must be a non-empty string')\n }\n return mappingSingle({\n idType: 'ID_SEDOL',\n idValue: sedol.trim(),\n ...options,\n })\n }\n\n /**\n * Search for FIGI by ticker symbol\n *\n * @param ticker - Ticker symbol (e.g., 'AAPL')\n * @param exchCode - Optional exchange code (e.g., 'US')\n * @param options - Additional search options\n * @returns Mapping response with FIGI data\n *\n * @example\n * ```typescript\n * const result = await searchByTicker('AAPL', 'US')\n * ```\n */\n const searchByTicker = async (\n ticker: string,\n exchCode?: string,\n options?: Partial<MappingRequest>\n ): Promise<MappingResponse> => {\n if (!ticker || typeof ticker !== 'string') {\n throw new ValidationError('Ticker must be a non-empty string')\n }\n return mappingSingle({\n idType: 'ID_EXCH_SYMBOL',\n idValue: ticker.trim().toUpperCase(),\n exchCode: exchCode?.trim(),\n ...options,\n })\n }\n\n /**\n * Search for FIGI by Bloomberg ID\n *\n * @param bbgId - Bloomberg Global ID (e.g., 'BBG000B9XRY4')\n * @param options - Additional search options\n * @returns Mapping response with FIGI data\n */\n const searchByBloombergId = async (\n bbgId: string,\n options?: Partial<MappingRequest>\n ): Promise<MappingResponse> => {\n if (!bbgId || typeof bbgId !== 'string') {\n throw new ValidationError('Bloomberg ID must be a non-empty string')\n }\n return mappingSingle({\n idType: 'ID_BB_GLOBAL',\n idValue: bbgId.trim(),\n ...options,\n })\n }\n\n /**\n * Get current rate limit information\n *\n * @returns Rate limit info if available, undefined if no requests made yet\n *\n * @example\n * ```typescript\n * const rateLimit = getRateLimitInfo()\n * if (rateLimit) {\n * console.log(`${rateLimit.remaining} requests remaining`)\n * }\n * ```\n */\n const getRateLimitInfo = (): RateLimitInfo | undefined => {\n return currentRateLimitInfo\n }\n\n return {\n mapping,\n mappingSingle,\n searchByISIN,\n searchByCUSIP,\n searchBySEDOL,\n searchByTicker,\n searchByBloombergId,\n getRateLimitInfo,\n }\n}\n\n// Export standalone functions with default client\nconst defaultClient = createClient()\n\nexport const mapping = defaultClient.mapping\nexport const mappingSingle = defaultClient.mappingSingle\nexport const searchByISIN = defaultClient.searchByISIN\nexport const searchByCUSIP = defaultClient.searchByCUSIP\nexport const searchBySEDOL = defaultClient.searchBySEDOL\nexport const searchByTicker = defaultClient.searchByTicker\nexport const searchByBloombergId = defaultClient.searchByBloombergId\nexport const getRateLimitInfo = defaultClient.getRateLimitInfo\n","/**\n * Validate ISIN format (12 characters, alphanumeric)\n */\nexport const isValidISIN = (isin: string): boolean => {\n return /^[A-Z]{2}[A-Z0-9]{9}[0-9]$/.test(isin)\n}\n\n/**\n * Validate CUSIP format (9 characters, alphanumeric)\n */\nexport const isValidCUSIP = (cusip: string): boolean => {\n return /^[A-Z0-9]{9}$/.test(cusip)\n}\n\n/**\n * Validate SEDOL format (7 characters, alphanumeric)\n */\nexport const isValidSEDOL = (sedol: string): boolean => {\n return /^[A-Z0-9]{7}$/.test(sedol)\n}\n\n/**\n * Validate Bloomberg ID format (starts with BBG)\n */\nexport const isValidBloombergId = (bbgId: string): boolean => {\n return /^BBG[A-Z0-9]{9}$/.test(bbgId)\n}\n\n/**\n * Split array into batches of specified size\n * Useful for splitting large arrays for batch processing\n */\nexport const batchArray = <T>(array: T[], batchSize: number): T[][] => {\n const batches: T[][] = []\n for (let i = 0; i < array.length; i += batchSize) {\n batches.push(array.slice(i, i + batchSize))\n }\n return batches\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openfigi-sdk",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Unofficial TypeScript SDK for OpenFIGI API - Map financial identifiers to FIGIs (community-maintained)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public",
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.mjs",
|
|
17
|
+
"require": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"test": "vitest",
|
|
29
|
+
"test:ui": "vitest --ui",
|
|
30
|
+
"test:coverage": "vitest run --coverage",
|
|
31
|
+
"lint": "biome check --write .",
|
|
32
|
+
"format": "biome format --write .",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"docs": "typedoc",
|
|
35
|
+
"changeset": "changeset",
|
|
36
|
+
"version": "changeset version",
|
|
37
|
+
"release": "bun run build && bun run test && bunx changeset publish",
|
|
38
|
+
"prepublishOnly": "bun run build && bun run test && bun run lint && bun run typecheck",
|
|
39
|
+
"pre-publish": "bun scripts/pre-publish.ts"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"openfigi",
|
|
43
|
+
"figi",
|
|
44
|
+
"finance",
|
|
45
|
+
"api",
|
|
46
|
+
"sdk",
|
|
47
|
+
"typescript",
|
|
48
|
+
"financial-identifiers",
|
|
49
|
+
"bloomberg"
|
|
50
|
+
],
|
|
51
|
+
"author": "",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/viktorlarsson/openfigi.git"
|
|
56
|
+
},
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/viktorlarsson/openfigi/issues"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/viktorlarsson/openfigi#readme",
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@biomejs/biome": "^2.3.11",
|
|
63
|
+
"@changesets/cli": "^2.29.8",
|
|
64
|
+
"@types/bun": "^1.3.6",
|
|
65
|
+
"@types/node": "^25.0.9",
|
|
66
|
+
"@vitest/ui": "^4.0.17",
|
|
67
|
+
"tsup": "^8.5.1",
|
|
68
|
+
"tsx": "^4.21.0",
|
|
69
|
+
"typedoc": "^0.28.16",
|
|
70
|
+
"vitest": "^4.0.17"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"typescript": "^5.9.3"
|
|
74
|
+
},
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"ky": "^1.14.2",
|
|
77
|
+
"zod": "^4.3.5"
|
|
78
|
+
}
|
|
79
|
+
}
|