bbdata-cli 0.1.0 → 0.1.1

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.
@@ -165,8 +165,8 @@ var SavantAdapter = class {
165
165
  }
166
166
  const params = new URLSearchParams({
167
167
  all: "true",
168
- type: "detail",
169
- ...query2.stat_type === "pitching" ? { player_type: "pitcher", pitchers_lookup: playerId ?? "" } : { player_type: "batter", batters_lookup: playerId ?? "" },
168
+ type: "details",
169
+ ...query2.stat_type === "pitching" ? { player_type: "pitcher", "pitchers_lookup[]": playerId ?? "" } : { player_type: "batter", "batters_lookup[]": playerId ?? "" },
170
170
  ...query2.start_date ? { game_date_gt: query2.start_date } : { game_date_gt: `${query2.season}-01-01` },
171
171
  ...query2.end_date ? { game_date_lt: query2.end_date } : { game_date_lt: `${query2.season}-12-31` }
172
172
  });
@@ -192,6 +192,9 @@ var SavantAdapter = class {
192
192
  cast: true,
193
193
  cast_date: false
194
194
  });
195
+ if (rawRows.length === 0 && csvText.trim().length > 50) {
196
+ log.debug("Savant returned headers but no data rows");
197
+ }
195
198
  const filteredRows = rawRows.filter(
196
199
  (row) => row.pitch_type && String(row.pitch_type).trim() !== ""
197
200
  );
@@ -231,6 +234,7 @@ var SavantAdapter = class {
231
234
 
232
235
  // src/adapters/fangraphs.ts
233
236
  var FG_LEADERS_URL = "https://www.fangraphs.com/api/leaders/major-league/data";
237
+ var stripHtml = (s) => s.replace(/<[^>]*>/g, "");
234
238
  var FanGraphsAdapter = class {
235
239
  source = "fangraphs";
236
240
  description = "FanGraphs \u2014 aggregated stats, leaderboards, WAR, wRC+, FIP";
@@ -259,7 +263,7 @@ var FanGraphsAdapter = class {
259
263
  const parsed = JSON.parse(data);
260
264
  const nameNorm = name.toLowerCase().trim();
261
265
  const players = parsed.data ?? [];
262
- const getName = (p) => String(p.PlayerName ?? p.Name ?? "").toLowerCase().trim();
266
+ const getName = (p) => stripHtml(String(p.PlayerName ?? p.Name ?? "")).toLowerCase().trim();
263
267
  let match = players.find((p) => getName(p) === nameNorm);
264
268
  if (!match) {
265
269
  const tokens = nameNorm.split(/\s+/);
@@ -275,8 +279,8 @@ var FanGraphsAdapter = class {
275
279
  return {
276
280
  mlbam_id: String(match.xMLBAMID ?? ""),
277
281
  fangraphs_id: String(match.playerid ?? ""),
278
- name: String(match.PlayerName ?? match.Name),
279
- team: String(match.Team ?? "")
282
+ name: stripHtml(String(match.PlayerName ?? match.Name)),
283
+ team: stripHtml(String(match.TeamNameAbb ?? match.TeamName ?? match.Team ?? ""))
280
284
  };
281
285
  } catch (error) {
282
286
  log.warn(`FanGraphs player resolution failed: ${error}`);
@@ -308,7 +312,7 @@ var FanGraphsAdapter = class {
308
312
  let filtered = rows;
309
313
  if (query2.player_name) {
310
314
  const nameNorm = query2.player_name.toLowerCase().trim();
311
- const getName = (r) => String(r.PlayerName ?? r.Name ?? "").toLowerCase().trim();
315
+ const getName = (r) => stripHtml(String(r.PlayerName ?? r.Name ?? "")).toLowerCase().trim();
312
316
  const exact = rows.filter((r) => getName(r) === nameNorm);
313
317
  if (exact.length > 0) {
314
318
  filtered = exact;
@@ -322,8 +326,8 @@ var FanGraphsAdapter = class {
322
326
  }
323
327
  const stats = filtered.map((row) => ({
324
328
  player_id: String(row.xMLBAMID ?? row.playerid ?? ""),
325
- player_name: String(row.PlayerName ?? row.Name ?? ""),
326
- team: String(row.Team ?? ""),
329
+ player_name: stripHtml(String(row.PlayerName ?? row.Name ?? "")),
330
+ team: stripHtml(String(row.TeamNameAbb ?? row.TeamName ?? row.Team ?? "")),
327
331
  season: query2.season,
328
332
  stat_type: query2.stat_type,
329
333
  stats: row
@@ -1174,11 +1178,12 @@ var template9 = {
1174
1178
  "bbdata query leaderboard-custom --stat ERA --min-ip 100 --top 10 --format table"
1175
1179
  ],
1176
1180
  buildQuery(params) {
1181
+ const pitchingStats = ["era", "fip", "xfip", "siera", "whip", "k/9", "bb/9", "hr/9", "ip", "w", "sv", "hld"];
1182
+ const isPitching = pitchingStats.includes((params.stat ?? "").toLowerCase());
1177
1183
  return {
1178
1184
  season: params.season ?? (/* @__PURE__ */ new Date()).getFullYear(),
1179
1185
  team: params.team,
1180
- stat_type: "batting",
1181
- // Will be overridden based on stat
1186
+ stat_type: isPitching ? "pitching" : "batting",
1182
1187
  min_pa: params.minPa,
1183
1188
  min_ip: params.minIp
1184
1189
  };
@@ -1464,6 +1469,10 @@ ${available}`);
1464
1469
  });
1465
1470
  const rows = template13.transform(adapterResult.data, params);
1466
1471
  const columns = template13.columns(params);
1472
+ if (rows.length === 0) {
1473
+ log.debug(`${adapter.source} returned 0 rows. Trying next source...`);
1474
+ continue;
1475
+ }
1467
1476
  result = {
1468
1477
  rows,
1469
1478
  columns,