bbdata-cli 0.1.1 → 0.2.0

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.
Files changed (35) hide show
  1. package/dist/bin/bbdata.js +109 -6
  2. package/dist/bin/bbdata.js.map +1 -1
  3. package/dist/src/index.d.ts +3 -1
  4. package/dist/src/index.js +103 -2
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/templates/queries/hitter-batted-ball.ts +66 -0
  7. package/dist/templates/queries/hitter-hot-cold-zones.ts +81 -0
  8. package/dist/templates/queries/hitter-vs-pitch-type.ts +78 -0
  9. package/dist/templates/queries/index.ts +24 -0
  10. package/dist/templates/queries/leaderboard-comparison.ts +72 -0
  11. package/dist/templates/queries/leaderboard-custom.ts +90 -0
  12. package/dist/templates/queries/matchup-pitcher-vs-hitter.ts +81 -0
  13. package/dist/templates/queries/matchup-situational.ts +68 -0
  14. package/dist/templates/queries/pitcher-arsenal.ts +89 -0
  15. package/dist/templates/queries/pitcher-handedness-splits.ts +81 -0
  16. package/dist/templates/queries/pitcher-velocity-trend.ts +73 -0
  17. package/dist/templates/queries/registry.ts +73 -0
  18. package/dist/templates/queries/trend-rolling-average.ts +86 -0
  19. package/dist/templates/queries/trend-year-over-year.ts +73 -0
  20. package/dist/templates/reports/advance-lineup.hbs +29 -0
  21. package/dist/templates/reports/advance-sp.hbs +60 -0
  22. package/dist/templates/reports/college-hitter-draft.hbs +49 -0
  23. package/dist/templates/reports/college-pitcher-draft.hbs +48 -0
  24. package/dist/templates/reports/dev-progress.hbs +29 -0
  25. package/dist/templates/reports/draft-board-card.hbs +35 -0
  26. package/dist/templates/reports/hs-prospect.hbs +48 -0
  27. package/dist/templates/reports/partials/footer.hbs +7 -0
  28. package/dist/templates/reports/partials/header.hbs +12 -0
  29. package/dist/templates/reports/post-promotion.hbs +25 -0
  30. package/dist/templates/reports/pro-hitter-eval.hbs +65 -0
  31. package/dist/templates/reports/pro-pitcher-eval.hbs +69 -0
  32. package/dist/templates/reports/registry.ts +215 -0
  33. package/dist/templates/reports/relief-pitcher-quick.hbs +29 -0
  34. package/dist/templates/reports/trade-target-onepager.hbs +45 -0
  35. package/package.json +1 -1
@@ -401,13 +401,88 @@ var BaseballReferenceAdapter = class {
401
401
  }
402
402
  };
403
403
 
404
+ // src/adapters/stdin.ts
405
+ var StdinAdapter = class {
406
+ source = "stdin";
407
+ description = "Local data from stdin (for sandboxed environments)";
408
+ data = [];
409
+ player = null;
410
+ loaded = false;
411
+ /**
412
+ * Load data from a pre-read stdin string.
413
+ * Called by the CLI before the adapter is used.
414
+ */
415
+ load(raw) {
416
+ try {
417
+ const parsed = JSON.parse(raw);
418
+ if (Array.isArray(parsed)) {
419
+ this.data = parsed;
420
+ } else if (parsed.data && Array.isArray(parsed.data)) {
421
+ this.data = parsed.data;
422
+ if (parsed.player) {
423
+ this.player = parsed.player;
424
+ }
425
+ } else {
426
+ throw new Error('Expected JSON array or { "data": [...] } object');
427
+ }
428
+ this.loaded = true;
429
+ log.info(`Stdin adapter loaded ${this.data.length} records`);
430
+ } catch (error) {
431
+ throw new Error(
432
+ `Failed to parse stdin data: ${error instanceof Error ? error.message : String(error)}`
433
+ );
434
+ }
435
+ }
436
+ supports(_query) {
437
+ return this.loaded && this.data.length > 0;
438
+ }
439
+ async fetch(query2) {
440
+ if (!this.loaded) {
441
+ throw new Error("Stdin adapter has no data \u2014 pipe JSON via stdin with --stdin flag");
442
+ }
443
+ return {
444
+ data: this.data,
445
+ source: "stdin",
446
+ cached: false,
447
+ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
448
+ meta: {
449
+ rowCount: this.data.length,
450
+ season: query2.season,
451
+ query: query2
452
+ }
453
+ };
454
+ }
455
+ async resolvePlayer(name) {
456
+ if (this.player && this.player.name.toLowerCase() === name.toLowerCase()) {
457
+ return this.player;
458
+ }
459
+ const firstRecord = this.data[0];
460
+ if (firstRecord) {
461
+ const id = firstRecord.pitcher_id ?? firstRecord.player_id ?? "";
462
+ const recordName = firstRecord.pitcher_name ?? firstRecord.player_name ?? name;
463
+ if (id) {
464
+ return {
465
+ mlbam_id: id,
466
+ name: recordName
467
+ };
468
+ }
469
+ }
470
+ return null;
471
+ }
472
+ };
473
+
404
474
  // src/adapters/index.ts
475
+ var stdinAdapter = new StdinAdapter();
405
476
  var adapters = {
406
477
  "mlb-stats-api": new MlbStatsApiAdapter(),
407
478
  "savant": new SavantAdapter(),
408
479
  "fangraphs": new FanGraphsAdapter(),
409
- "baseball-reference": new BaseballReferenceAdapter()
480
+ "baseball-reference": new BaseballReferenceAdapter(),
481
+ "stdin": stdinAdapter
410
482
  };
483
+ function getStdinAdapter() {
484
+ return stdinAdapter;
485
+ }
411
486
  function resolveAdapters(preferred) {
412
487
  return preferred.map((source) => adapters[source]).filter(Boolean);
413
488
  }
@@ -578,6 +653,20 @@ function getTemplatesDir() {
578
653
  return dir;
579
654
  }
580
655
 
656
+ // src/utils/stdin.ts
657
+ function readStdin() {
658
+ return new Promise((resolve, reject) => {
659
+ if (process.stdin.isTTY) {
660
+ reject(new Error(`--stdin flag requires piped input. Usage: echo '{"data":[...]}' | bbdata query ... --stdin`));
661
+ return;
662
+ }
663
+ const chunks = [];
664
+ process.stdin.on("data", (chunk) => chunks.push(chunk));
665
+ process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
666
+ process.stdin.on("error", reject);
667
+ });
668
+ }
669
+
581
670
  // src/templates/queries/registry.ts
582
671
  var templates = /* @__PURE__ */ new Map();
583
672
  function registerTemplate(template13) {
@@ -1429,6 +1518,12 @@ registerTemplate(template12);
1429
1518
 
1430
1519
  // src/commands/query.ts
1431
1520
  async function query(options) {
1521
+ if (options.stdin) {
1522
+ const raw = await readStdin();
1523
+ const adapter = getStdinAdapter();
1524
+ adapter.load(raw);
1525
+ options.source = "stdin";
1526
+ }
1432
1527
  const config = getConfig();
1433
1528
  const outputFormat = options.format ?? config.defaultFormat;
1434
1529
  const template13 = getTemplate(options.template);
@@ -1512,7 +1607,7 @@ ${available}`);
1512
1607
  };
1513
1608
  }
1514
1609
  function registerQueryCommand(program2) {
1515
- const cmd = program2.command("query [template]").description("Query baseball data using pre-built templates").option("-p, --player <name>", "Player name").option("--players <names>", "Comma-separated player names (for matchups/comparisons)").option("-s, --season <year>", "Season year", String((/* @__PURE__ */ new Date()).getFullYear())).option("-f, --format <fmt>", "Output: json, table, csv, markdown", "json").option("--source <src>", "Force a data source: savant, fangraphs, mlb-stats-api").option("--stat <stat>", "Stat to query (for leaderboards)").option("--pitch-type <type>", "Filter by pitch type (e.g., FF, SL)").option("--min-pa <n>", "Minimum plate appearances", parseInt).option("--min-ip <n>", "Minimum innings pitched", parseInt).option("--top <n>", "Number of results for leaderboards", parseInt).option("--seasons <range>", "Season range (e.g., 2023-2025)").option("--no-cache", "Bypass cache").addHelpText("after", `
1610
+ const cmd = program2.command("query [template]").description("Query baseball data using pre-built templates").option("-p, --player <name>", "Player name").option("--players <names>", "Comma-separated player names (for matchups/comparisons)").option("-s, --season <year>", "Season year", String((/* @__PURE__ */ new Date()).getFullYear())).option("-f, --format <fmt>", "Output: json, table, csv, markdown", "json").option("--source <src>", "Force a data source: savant, fangraphs, mlb-stats-api").option("--stat <stat>", "Stat to query (for leaderboards)").option("--pitch-type <type>", "Filter by pitch type (e.g., FF, SL)").option("--min-pa <n>", "Minimum plate appearances", parseInt).option("--min-ip <n>", "Minimum innings pitched", parseInt).option("--top <n>", "Number of results for leaderboards", parseInt).option("--seasons <range>", "Season range (e.g., 2023-2025)").option("--no-cache", "Bypass cache").option("--stdin", "Read pre-fetched JSON data from stdin instead of fetching from APIs").addHelpText("after", `
1516
1611
  Examples:
1517
1612
  bbdata query pitcher-arsenal --player "Corbin Burnes" --season 2025
1518
1613
  bbdata query hitter-batted-ball --player "Aaron Judge" --format table
@@ -1551,7 +1646,8 @@ Available templates:
1551
1646
  seasons: opts.seasons,
1552
1647
  format: opts.format,
1553
1648
  source: opts.source,
1554
- cache: opts.cache
1649
+ cache: opts.cache,
1650
+ stdin: opts.stdin
1555
1651
  });
1556
1652
  log.data(result.formatted);
1557
1653
  } catch (error) {
@@ -1816,6 +1912,11 @@ ${sections}
1816
1912
  `;
1817
1913
  }
1818
1914
  async function report(options) {
1915
+ if (options.stdin) {
1916
+ const raw = await readStdin();
1917
+ const adapter = getStdinAdapter();
1918
+ adapter.load(raw);
1919
+ }
1819
1920
  const config = getConfig();
1820
1921
  const audience = options.audience ?? config.defaultAudience;
1821
1922
  const template13 = getReportTemplate(options.template);
@@ -1835,7 +1936,8 @@ ${available}`);
1835
1936
  player: options.player,
1836
1937
  team: options.team,
1837
1938
  season,
1838
- format: "json"
1939
+ format: "json",
1940
+ ...options.stdin ? { source: "stdin" } : {}
1839
1941
  });
1840
1942
  dataResults[req.queryTemplate] = result.data;
1841
1943
  if (!dataSources.includes(result.meta.source)) {
@@ -1902,7 +2004,7 @@ function validateReport(content, requiredSections) {
1902
2004
  };
1903
2005
  }
1904
2006
  function registerReportCommand(program2) {
1905
- program2.command("report [template]").description("Generate scouting reports using pre-built templates").option("-p, --player <name>", "Player name").option("-t, --team <code>", "Team abbreviation").option("-s, --season <year>", "Season year", String((/* @__PURE__ */ new Date()).getFullYear())).option("-a, --audience <role>", "Target audience: coach, gm, scout, analyst").option("-f, --format <fmt>", "Output: markdown, json", "markdown").option("--validate", "Run validation checklist on the report").addHelpText("after", `
2007
+ program2.command("report [template]").description("Generate scouting reports using pre-built templates").option("-p, --player <name>", "Player name").option("-t, --team <code>", "Team abbreviation").option("-s, --season <year>", "Season year", String((/* @__PURE__ */ new Date()).getFullYear())).option("-a, --audience <role>", "Target audience: coach, gm, scout, analyst").option("-f, --format <fmt>", "Output: markdown, json", "markdown").option("--validate", "Run validation checklist on the report").option("--stdin", "Read pre-fetched JSON data from stdin instead of fetching from APIs").addHelpText("after", `
1906
2008
  Examples:
1907
2009
  bbdata report pro-pitcher-eval --player "Corbin Burnes"
1908
2010
  bbdata report advance-sp --player "Gerrit Cole" --audience coach --validate
@@ -1933,7 +2035,8 @@ Available templates:
1933
2035
  season: opts.season ? parseInt(opts.season) : void 0,
1934
2036
  audience: opts.audience,
1935
2037
  format: opts.format,
1936
- validate: opts.validate
2038
+ validate: opts.validate,
2039
+ stdin: opts.stdin
1937
2040
  });
1938
2041
  log.data(result.formatted);
1939
2042
  if (result.validation && !result.validation.passed) {