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