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.
- package/dist/bin/bbdata.js +109 -6
- package/dist/bin/bbdata.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.js +103 -2
- package/dist/src/index.js.map +1 -1
- package/dist/templates/queries/hitter-batted-ball.ts +66 -0
- package/dist/templates/queries/hitter-hot-cold-zones.ts +81 -0
- package/dist/templates/queries/hitter-vs-pitch-type.ts +78 -0
- package/dist/templates/queries/index.ts +24 -0
- package/dist/templates/queries/leaderboard-comparison.ts +72 -0
- package/dist/templates/queries/leaderboard-custom.ts +90 -0
- package/dist/templates/queries/matchup-pitcher-vs-hitter.ts +81 -0
- package/dist/templates/queries/matchup-situational.ts +68 -0
- package/dist/templates/queries/pitcher-arsenal.ts +89 -0
- package/dist/templates/queries/pitcher-handedness-splits.ts +81 -0
- package/dist/templates/queries/pitcher-velocity-trend.ts +73 -0
- package/dist/templates/queries/registry.ts +73 -0
- package/dist/templates/queries/trend-rolling-average.ts +86 -0
- package/dist/templates/queries/trend-year-over-year.ts +73 -0
- package/dist/templates/reports/advance-lineup.hbs +29 -0
- package/dist/templates/reports/advance-sp.hbs +60 -0
- package/dist/templates/reports/college-hitter-draft.hbs +49 -0
- package/dist/templates/reports/college-pitcher-draft.hbs +48 -0
- package/dist/templates/reports/dev-progress.hbs +29 -0
- package/dist/templates/reports/draft-board-card.hbs +35 -0
- package/dist/templates/reports/hs-prospect.hbs +48 -0
- package/dist/templates/reports/partials/footer.hbs +7 -0
- package/dist/templates/reports/partials/header.hbs +12 -0
- package/dist/templates/reports/post-promotion.hbs +25 -0
- package/dist/templates/reports/pro-hitter-eval.hbs +65 -0
- package/dist/templates/reports/pro-pitcher-eval.hbs +69 -0
- package/dist/templates/reports/registry.ts +215 -0
- package/dist/templates/reports/relief-pitcher-quick.hbs +29 -0
- package/dist/templates/reports/trade-target-onepager.hbs +45 -0
- package/package.json +1 -1
package/dist/bin/bbdata.js
CHANGED
|
@@ -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) {
|