@xbbg/core 1.3.1 → 1.4.2

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/dist/index.js CHANGED
@@ -22,7 +22,7 @@ function tableFromNativeArrowBatch(batch) {
22
22
  return new apacheArrow.Field(column.name, type, column.nullable);
23
23
  });
24
24
  const children = batch.columns.map((column) => dataFromColumn(column, retainedBuffers));
25
- const schema = new apacheArrow.Schema(fields);
25
+ const schema = new apacheArrow.Schema(fields, new Map(Object.entries(batch.metadata)));
26
26
  const structData = apacheArrow.makeData({
27
27
  children,
28
28
  length: batch.numRows,
@@ -1078,7 +1078,83 @@ var TA_DEFAULTS = Object.freeze({
1078
1078
  });
1079
1079
  var MKTDATA_SERVICE = "//blp/mktdata";
1080
1080
  function toArrowTableFromNative(batch) {
1081
- return tableFromNativeArrowBatch(batch);
1081
+ return attachResultMetadata(tableFromNativeArrowBatch(batch), batch.metadata);
1082
+ }
1083
+ var METADATA_KEY_EID_DATA = "xbbg.eid_data";
1084
+ var METADATA_KEY_SECURITY_ERRORS = "xbbg.security_errors";
1085
+ var METADATA_KEY_FIELD_EXCEPTIONS = "xbbg.field_exceptions";
1086
+ function metadataRecordFromMap(metadata) {
1087
+ return Object.fromEntries(metadata.entries());
1088
+ }
1089
+ function parseJsonMetadata(metadata, key, guard) {
1090
+ const raw = metadata[key];
1091
+ if (raw === void 0) {
1092
+ return void 0;
1093
+ }
1094
+ try {
1095
+ const parsed = JSON.parse(raw);
1096
+ return guard(parsed) ? parsed : void 0;
1097
+ } catch {
1098
+ return void 0;
1099
+ }
1100
+ }
1101
+ function isNumberArrayRecord(value) {
1102
+ if (!isPlainObject(value)) {
1103
+ return false;
1104
+ }
1105
+ return Object.values(value).every(
1106
+ (entry) => Array.isArray(entry) && entry.every((eid) => typeof eid === "number")
1107
+ );
1108
+ }
1109
+ function isMetadataError(value) {
1110
+ if (!isPlainObject(value)) {
1111
+ return false;
1112
+ }
1113
+ const { category, code, message, subcategory } = value;
1114
+ return (category === void 0 || typeof category === "string") && (code === void 0 || typeof code === "string" || typeof code === "number") && (message === void 0 || typeof message === "string") && (subcategory === void 0 || typeof subcategory === "string");
1115
+ }
1116
+ function isMetadataErrorRecord(value) {
1117
+ if (!isPlainObject(value)) {
1118
+ return false;
1119
+ }
1120
+ return Object.values(value).every(isMetadataError);
1121
+ }
1122
+ function isFieldException(value) {
1123
+ if (!isMetadataError(value)) {
1124
+ return false;
1125
+ }
1126
+ if (!("field" in value)) {
1127
+ return true;
1128
+ }
1129
+ return typeof value.field === "string";
1130
+ }
1131
+ function isFieldExceptionRecord(value) {
1132
+ if (!isPlainObject(value)) {
1133
+ return false;
1134
+ }
1135
+ return Object.values(value).every(
1136
+ (entry) => Array.isArray(entry) && entry.every(isFieldException)
1137
+ );
1138
+ }
1139
+ function attachResultMetadata(result, metadata) {
1140
+ const eidData = parseJsonMetadata(metadata, METADATA_KEY_EID_DATA, isNumberArrayRecord);
1141
+ const securityErrors = parseJsonMetadata(
1142
+ metadata,
1143
+ METADATA_KEY_SECURITY_ERRORS,
1144
+ isMetadataErrorRecord
1145
+ );
1146
+ const fieldExceptions = parseJsonMetadata(
1147
+ metadata,
1148
+ METADATA_KEY_FIELD_EXCEPTIONS,
1149
+ isFieldExceptionRecord
1150
+ );
1151
+ Object.defineProperties(result, {
1152
+ eidData: { enumerable: true, value: eidData },
1153
+ fieldExceptions: { enumerable: true, value: fieldExceptions },
1154
+ metadata: { enumerable: true, value: { ...metadata } },
1155
+ securityErrors: { enumerable: true, value: securityErrors }
1156
+ });
1157
+ return result;
1082
1158
  }
1083
1159
  function isPlainObject(value) {
1084
1160
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1086,6 +1162,12 @@ function isPlainObject(value) {
1086
1162
  function toRequestString(value) {
1087
1163
  return String(value);
1088
1164
  }
1165
+ function getLegacySecurityOverrides(params) {
1166
+ if ("securityOverrides" in params) {
1167
+ return params.securityOverrides;
1168
+ }
1169
+ return void 0;
1170
+ }
1089
1171
  function mapObjectToPairs(obj) {
1090
1172
  if (obj === void 0) {
1091
1173
  return void 0;
@@ -1095,6 +1177,189 @@ function mapObjectToPairs(obj) {
1095
1177
  value: toRequestString(value)
1096
1178
  }));
1097
1179
  }
1180
+ var OVR_SOURCE_TYPE_ERROR = "ovr() expects objects, OverrideSpec, or arrays of override entries";
1181
+ function normalizeOverrideValue(value) {
1182
+ if (value instanceof Date || hasToJSDate(value)) {
1183
+ return formatDate(value) ?? "";
1184
+ }
1185
+ return String(value);
1186
+ }
1187
+ function isOverrideSpecLike(value) {
1188
+ return isPlainObject(value) && Array.isArray(value.pairs) && typeof value.toPairs === "function" && typeof value.toObject === "function" && typeof value.merge === "function";
1189
+ }
1190
+ function isOverrideObject(value) {
1191
+ return isPlainObject(value) && !(value instanceof Date) && !hasToJSDate(value) && !isOverrideSpecLike(value) && !ArrayBuffer.isView(value);
1192
+ }
1193
+ function normalizeOverrideEntry(entry) {
1194
+ if (Array.isArray(entry)) {
1195
+ if (entry.length !== 2) {
1196
+ throw new TypeError(OVR_SOURCE_TYPE_ERROR);
1197
+ }
1198
+ return [String(entry[0]), entry[1]];
1199
+ }
1200
+ if (isPlainObject(entry) && "key" in entry && "value" in entry) {
1201
+ return [String(entry.key), entry.value];
1202
+ }
1203
+ throw new TypeError(OVR_SOURCE_TYPE_ERROR);
1204
+ }
1205
+ function createOverrideState() {
1206
+ return {
1207
+ merged: /* @__PURE__ */ new Map(),
1208
+ securityMerged: /* @__PURE__ */ new Map(),
1209
+ securityOrder: []
1210
+ };
1211
+ }
1212
+ function isPerSecurityOverrideValue(value) {
1213
+ return isOverrideSpecLike(value) || Array.isArray(value) || isOverrideObject(value);
1214
+ }
1215
+ function addSecurityOverrideSource(security, source, state) {
1216
+ const spec = ovr(source);
1217
+ const pairs = spec.toPairs();
1218
+ if (pairs.length === 0) {
1219
+ return;
1220
+ }
1221
+ let merged = state.securityMerged.get(security);
1222
+ if (merged === void 0) {
1223
+ merged = /* @__PURE__ */ new Map();
1224
+ state.securityMerged.set(security, merged);
1225
+ state.securityOrder.push(security);
1226
+ }
1227
+ for (const pair of pairs) {
1228
+ merged.set(pair.key, pair.value);
1229
+ }
1230
+ }
1231
+ function addOverridePair(key, value, state) {
1232
+ if (isPerSecurityOverrideValue(value)) {
1233
+ addSecurityOverrideSource(key, value, state);
1234
+ return;
1235
+ }
1236
+ state.merged.set(key, normalizeOverrideValue(value));
1237
+ }
1238
+ function addOverrideSource(source, state) {
1239
+ if (typeof source === "string" || ArrayBuffer.isView(source)) {
1240
+ throw new TypeError(OVR_SOURCE_TYPE_ERROR);
1241
+ }
1242
+ if (isOverrideSpecLike(source)) {
1243
+ for (const pair of source.toPairs()) {
1244
+ state.merged.set(pair.key, normalizeOverrideValue(pair.value));
1245
+ }
1246
+ const securityOverrides = typeof source.toSecurityOverrides === "function" ? source.toSecurityOverrides() : source.securityOverrides ?? [];
1247
+ for (const entry of securityOverrides) {
1248
+ addSecurityOverrideSource(entry.security, entry.overrides, state);
1249
+ }
1250
+ return;
1251
+ }
1252
+ if (Array.isArray(source)) {
1253
+ for (const entry of source) {
1254
+ const [key, value] = normalizeOverrideEntry(entry);
1255
+ addOverridePair(key, value, state);
1256
+ }
1257
+ return;
1258
+ }
1259
+ if (isOverrideObject(source)) {
1260
+ for (const [key, value] of Object.entries(source)) {
1261
+ addOverridePair(key, value, state);
1262
+ }
1263
+ return;
1264
+ }
1265
+ throw new TypeError(OVR_SOURCE_TYPE_ERROR);
1266
+ }
1267
+ function securityOverridesFromState(state) {
1268
+ return state.securityOrder.flatMap((security) => {
1269
+ const pairs = state.securityMerged.get(security);
1270
+ if (pairs === void 0 || pairs.size === 0) {
1271
+ return [];
1272
+ }
1273
+ return [
1274
+ {
1275
+ overrides: [...pairs].map(([key, value]) => ({ key, value })),
1276
+ security
1277
+ }
1278
+ ];
1279
+ });
1280
+ }
1281
+ var OverrideSpec = class {
1282
+ pairs;
1283
+ securityOverrides;
1284
+ constructor(pairs, securityOverrides = []) {
1285
+ this.pairs = Object.freeze(
1286
+ pairs.map(
1287
+ (pair) => Object.freeze({
1288
+ key: pair.key,
1289
+ value: pair.value
1290
+ })
1291
+ )
1292
+ );
1293
+ this.securityOverrides = Object.freeze(
1294
+ securityOverrides.map(
1295
+ (entry) => Object.freeze({
1296
+ overrides: Object.freeze(
1297
+ entry.overrides.map(
1298
+ (pair) => Object.freeze({
1299
+ key: pair.key,
1300
+ value: pair.value
1301
+ })
1302
+ )
1303
+ ),
1304
+ security: entry.security
1305
+ })
1306
+ )
1307
+ );
1308
+ }
1309
+ [Symbol.iterator]() {
1310
+ return this.toPairs()[Symbol.iterator]();
1311
+ }
1312
+ toPairs() {
1313
+ return this.pairs.map((pair) => ({ key: pair.key, value: pair.value }));
1314
+ }
1315
+ toObject() {
1316
+ return Object.fromEntries(this.pairs.map((pair) => [pair.key, pair.value]));
1317
+ }
1318
+ toSecurityOverrides() {
1319
+ return this.securityOverrides.map((entry) => ({
1320
+ overrides: entry.overrides.map((pair) => ({ key: pair.key, value: pair.value })),
1321
+ security: entry.security
1322
+ }));
1323
+ }
1324
+ merge(...sources) {
1325
+ return ovr(this, ...sources);
1326
+ }
1327
+ forSecurity(security, ...sources) {
1328
+ return ovr(this, { [security]: ovr(...sources) });
1329
+ }
1330
+ };
1331
+ function ovr(...sources) {
1332
+ const state = createOverrideState();
1333
+ for (const source of sources) {
1334
+ addOverrideSource(source, state);
1335
+ }
1336
+ return new OverrideSpec(
1337
+ [...state.merged].map(([key, value]) => ({ key, value })),
1338
+ securityOverridesFromState(state)
1339
+ );
1340
+ }
1341
+ function mapOverridesToPairs(input) {
1342
+ if (input === void 0) {
1343
+ return void 0;
1344
+ }
1345
+ const spec = ovr(input);
1346
+ if (spec.toSecurityOverrides().length > 0) {
1347
+ throw new TypeError("Per-security overrides are only supported by bdp(), bdh(), and bds()");
1348
+ }
1349
+ return spec.toPairs();
1350
+ }
1351
+ function mapOverridesToRequestParts(input) {
1352
+ if (input === void 0) {
1353
+ return {};
1354
+ }
1355
+ const spec = ovr(input);
1356
+ const overrides = spec.toPairs();
1357
+ const securityOverrides = spec.toSecurityOverrides();
1358
+ return {
1359
+ ...overrides.length === 0 ? {} : { overrides },
1360
+ ...securityOverrides.length === 0 ? {} : { securityOverrides }
1361
+ };
1362
+ }
1098
1363
  var BDTICK_BOOLEAN_KWARGS = Object.freeze([
1099
1364
  ["includeConditionCodes", "includeConditionCodes"],
1100
1365
  ["includeExchangeCodes", "includeExchangeCodes"],
@@ -1225,10 +1490,9 @@ function normalizeRecoveryOptions(options = {}) {
1225
1490
  delete normalized.recoveryRate;
1226
1491
  delete normalized.recovery_rate;
1227
1492
  if (recoveryRate !== void 0) {
1228
- normalized.overrides = {
1229
- ...normalized.overrides,
1493
+ normalized.overrides = ovr(normalized.overrides ?? {}, {
1230
1494
  CDS_RR: toRequestString(recoveryRate)
1231
- };
1495
+ });
1232
1496
  }
1233
1497
  return normalized;
1234
1498
  }
@@ -1374,13 +1638,15 @@ function normalizeBackend(backend) {
1374
1638
  }
1375
1639
  function ipcToBackend(buffer, backend) {
1376
1640
  const selected = normalizeBackend(backend);
1641
+ const table = apacheArrow.tableFromIPC(buffer);
1642
+ const metadata = metadataRecordFromMap(table.schema.metadata);
1377
1643
  if (selected === Backend.JSON) {
1378
- return [...apacheArrow.tableFromIPC(buffer)];
1644
+ return attachResultMetadata([...table], metadata);
1379
1645
  }
1380
1646
  if (selected === Backend.POLARS) {
1381
1647
  return loadPolars().readIPC(buffer);
1382
1648
  }
1383
- return apacheArrow.tableFromIPC(buffer);
1649
+ return attachResultMetadata(table, metadata);
1384
1650
  }
1385
1651
  var configuredEngineConfig;
1386
1652
  var configuredEnginePromise;
@@ -1616,9 +1882,58 @@ var Engine = class _Engine {
1616
1882
  throw wrapError(error);
1617
1883
  }
1618
1884
  }
1885
+ /**
1886
+ * Return the Bloomberg identity seat type: "BPS", "NONBPS", or "INVALID".
1887
+ *
1888
+ * Identity operations authorize lazily using the engine auth config when
1889
+ * configured, otherwise the Desktop terminal OS-logon user. The first call
1890
+ * may block for a few seconds and transient failures are retryable.
1891
+ */
1892
+ async seatType() {
1893
+ try {
1894
+ return await this.inner.seatType();
1895
+ } catch (error) {
1896
+ throw wrapError(error);
1897
+ }
1898
+ }
1899
+ /**
1900
+ * Check whether the authorized identity is entitled to all supplied EIDs.
1901
+ *
1902
+ * Identity operations authorize lazily using the engine auth config when
1903
+ * configured, otherwise the Desktop terminal OS-logon user. The first call
1904
+ * may block for a few seconds and transient failures are retryable.
1905
+ */
1906
+ async checkEntitlements(service, eids) {
1907
+ try {
1908
+ return await this.inner.checkEntitlements(service, eids);
1909
+ } catch (error) {
1910
+ throw wrapError(error);
1911
+ }
1912
+ }
1913
+ /**
1914
+ * Return whether the authorized identity may use the Bloomberg service.
1915
+ *
1916
+ * Identity operations authorize lazily using the engine auth config when
1917
+ * configured, otherwise the Desktop terminal OS-logon user. The first call
1918
+ * may block for a few seconds and transient failures are retryable.
1919
+ */
1920
+ async identityIsAuthorized(service) {
1921
+ try {
1922
+ return await this.inner.identityIsAuthorized(service);
1923
+ } catch (error) {
1924
+ throw wrapError(error);
1925
+ }
1926
+ }
1619
1927
  async request(params) {
1620
1928
  const backend = normalizeBackend(params.backend);
1621
- const { backend: _discarded, ...nativeParams } = params;
1929
+ const { backend: _discarded, overrides, ...rest } = params;
1930
+ const legacySecurityOverrides = getLegacySecurityOverrides(params);
1931
+ if (legacySecurityOverrides !== void 0) {
1932
+ throw new TypeError(
1933
+ 'Use overrides: ovr({ "<SECURITY>": { ... } }) for per-security overrides'
1934
+ );
1935
+ }
1936
+ const nativeParams = { ...rest, ...mapOverridesToRequestParts(overrides) };
1622
1937
  try {
1623
1938
  const buffer = await this.inner.request(nativeParams);
1624
1939
  return ipcToBackend(buffer, backend);
@@ -1627,8 +1942,15 @@ var Engine = class _Engine {
1627
1942
  }
1628
1943
  }
1629
1944
  async requestRaw(params) {
1945
+ const { overrides, ...rest } = params;
1946
+ const legacySecurityOverrides = getLegacySecurityOverrides(params);
1947
+ if (legacySecurityOverrides !== void 0) {
1948
+ throw new TypeError(
1949
+ 'Use overrides: ovr({ "<SECURITY>": { ... } }) for per-security overrides'
1950
+ );
1951
+ }
1630
1952
  try {
1631
- return await this.inner.request(params);
1953
+ return await this.inner.request({ ...rest, ...mapOverridesToRequestParts(overrides) });
1632
1954
  } catch (error) {
1633
1955
  throw wrapError(error);
1634
1956
  }
@@ -1640,9 +1962,10 @@ var Engine = class _Engine {
1640
1962
  fields,
1641
1963
  format: options.format,
1642
1964
  includeSecurityErrors: Boolean(options.includeSecurityErrors),
1965
+ returnEids: options.returnEids,
1643
1966
  kwargs: mapObjectToPairs(options.kwargs),
1644
1967
  operation: "ReferenceDataRequest",
1645
- overrides: mapObjectToPairs(options.overrides),
1968
+ overrides: options.overrides,
1646
1969
  securities: tickers,
1647
1970
  service: "//blp/refdata",
1648
1971
  validateFields: options.validateFields
@@ -1654,9 +1977,10 @@ var Engine = class _Engine {
1654
1977
  extractor: "bulk",
1655
1978
  fields,
1656
1979
  format: options.format,
1980
+ returnEids: options.returnEids,
1657
1981
  kwargs: mapObjectToPairs(options.kwargs),
1658
1982
  operation: "ReferenceDataRequest",
1659
- overrides: mapObjectToPairs(options.overrides),
1983
+ overrides: options.overrides,
1660
1984
  securities: tickers,
1661
1985
  service: "//blp/refdata",
1662
1986
  validateFields: options.validateFields
@@ -1669,9 +1993,10 @@ var Engine = class _Engine {
1669
1993
  extractor: "histdata",
1670
1994
  fields,
1671
1995
  format: options.format,
1996
+ returnEids: options.returnEids,
1672
1997
  kwargs: mapObjectToPairs(options.kwargs),
1673
1998
  operation: "HistoricalDataRequest",
1674
- overrides: mapObjectToPairs(options.overrides),
1999
+ overrides: options.overrides,
1675
2000
  securities: tickers,
1676
2001
  service: "//blp/refdata",
1677
2002
  startDate: formatDate(options.start),
@@ -1732,7 +2057,6 @@ var Engine = class _Engine {
1732
2057
  elements.push({ key: "asOfDate", value: asofFormatted });
1733
2058
  }
1734
2059
  }
1735
- const overrides = { ...options.overrides };
1736
2060
  return await this.request({
1737
2061
  backend: options.backend,
1738
2062
  elements,
@@ -1740,19 +2064,19 @@ var Engine = class _Engine {
1740
2064
  format: options.format,
1741
2065
  kwargs: mapObjectToPairs(options.kwargs),
1742
2066
  operation: "BeqsRequest",
1743
- overrides: mapObjectToPairs(overrides),
2067
+ overrides: mapOverridesToPairs(options.overrides),
1744
2068
  service: "//blp/refdata"
1745
2069
  });
1746
2070
  }
1747
2071
  async bsrch(searchSpec, options = {}) {
1748
- const elements = {
1749
- Domain: toRequestString(searchSpec),
1750
- ...options.overrides,
1751
- ...options.kwargs
1752
- };
2072
+ const elements = [
2073
+ { key: "Domain", value: toRequestString(searchSpec) },
2074
+ ...mapOverridesToPairs(options.overrides) ?? [],
2075
+ ...mapObjectToPairs(options.kwargs) ?? []
2076
+ ];
1753
2077
  return await this.request({
1754
2078
  backend: options.backend,
1755
- elements: mapObjectToPairs(elements),
2079
+ elements,
1756
2080
  extractor: "bsrch",
1757
2081
  format: options.format,
1758
2082
  operation: "ExcelGetGridRequest",
@@ -1807,7 +2131,7 @@ var Engine = class _Engine {
1807
2131
  format: options.format,
1808
2132
  kwargs: mapObjectToPairs(options.kwargs),
1809
2133
  operation: "PortfolioDataRequest",
1810
- overrides: mapObjectToPairs(options.overrides),
2134
+ overrides: mapOverridesToPairs(options.overrides),
1811
2135
  security: toRequestString(portfolio),
1812
2136
  service: "//blp/refdata"
1813
2137
  });
@@ -2288,7 +2612,7 @@ async function bdh(tickers, fields, options = {}) {
2288
2612
  }
2289
2613
  async function abds(tickers, fields, overrides, options = {}) {
2290
2614
  const engine = await getConfiguredEngine();
2291
- const normalizedOptions = isPlainObject(overrides) ? { ...options, overrides: { ...options.overrides, ...overrides } } : options;
2615
+ const normalizedOptions = overrides === void 0 ? options : { ...options, overrides: ovr(options.overrides ?? {}, overrides) };
2292
2616
  return await engine.bds(toStringArray(tickers), toStringArray(fields), normalizedOptions);
2293
2617
  }
2294
2618
  async function bds(tickers, fields, options = {}) {
@@ -2438,6 +2762,7 @@ exports.CDX_RISK_FIELDS = CDX_RISK_FIELDS;
2438
2762
  exports.Engine = Engine;
2439
2763
  exports.FieldHandle = FieldHandle;
2440
2764
  exports.Format = Format;
2765
+ exports.OverrideSpec = OverrideSpec;
2441
2766
  exports.Subscription = Subscription;
2442
2767
  exports.Tick = Tick;
2443
2768
  exports.abdh = abdh;
@@ -2458,6 +2783,7 @@ exports.ext = ext;
2458
2783
  exports.formatDate = formatDate;
2459
2784
  exports.formatDateTime = formatDateTime;
2460
2785
  exports.getLogLevel = getLogLevel;
2786
+ exports.ovr = ovr;
2461
2787
  exports.setLogLevel = setLogLevel;
2462
2788
  exports.subscribe = subscribe;
2463
2789
  exports.version = version;