fitzroy 1.2.0 → 1.3.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/cli.js CHANGED
@@ -10,6 +10,12 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/lib/errors.ts
13
+ function aflwUnsupportedError(source) {
14
+ return new UnsupportedSourceError(
15
+ `AFLW data is not available from ${source}. Use --source afl-api for AFLW data.`,
16
+ source
17
+ );
18
+ }
13
19
  var AflApiError, ScrapeError, UnsupportedSourceError, ValidationError;
14
20
  var init_errors = __esm({
15
21
  "src/lib/errors.ts"() {
@@ -45,6 +51,47 @@ var init_errors = __esm({
45
51
  }
46
52
  });
47
53
 
54
+ // src/cli/error-boundary.ts
55
+ import pc from "picocolors";
56
+ function formatError(error) {
57
+ if (error instanceof ValidationError && error.issues) {
58
+ const issueLines = error.issues.map((i) => ` ${pc.yellow(i.path)}: ${i.message}`);
59
+ return `${pc.red("Validation error:")}
60
+ ${issueLines.join("\n")}`;
61
+ }
62
+ if (error instanceof AflApiError) {
63
+ const status = error.statusCode ? ` (HTTP ${error.statusCode})` : "";
64
+ return `${pc.red("AFL API error:")} ${error.message}${status}`;
65
+ }
66
+ if (error instanceof ScrapeError) {
67
+ const source = error.source ? ` [${error.source}]` : "";
68
+ return `${pc.red("Scrape error:")} ${error.message}${source}`;
69
+ }
70
+ if (error instanceof UnsupportedSourceError) {
71
+ return `${pc.red("Unsupported source:")} ${error.message}`;
72
+ }
73
+ if (error instanceof Error) {
74
+ return `${pc.red("Error:")} ${error.message}`;
75
+ }
76
+ return `${pc.red("Error:")} ${String(error)}`;
77
+ }
78
+ function withErrorBoundary(fn) {
79
+ return async (ctx) => {
80
+ try {
81
+ await fn(ctx);
82
+ } catch (error) {
83
+ console.error(formatError(error));
84
+ process.exit(1);
85
+ }
86
+ };
87
+ }
88
+ var init_error_boundary = __esm({
89
+ "src/cli/error-boundary.ts"() {
90
+ "use strict";
91
+ init_errors();
92
+ }
93
+ });
94
+
48
95
  // src/lib/result.ts
49
96
  function ok(data) {
50
97
  return { success: true, data };
@@ -117,6 +164,10 @@ function parseAflTablesDate(dateStr) {
117
164
  }
118
165
  return null;
119
166
  }
167
+ function resolveDefaultSeason(competition = "AFLM") {
168
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
169
+ return competition === "AFLW" ? year - 1 : year;
170
+ }
120
171
  function buildUtcDate(year, monthStr, day) {
121
172
  const monthIndex = MONTH_ABBREV_TO_INDEX.get(monthStr.toLowerCase());
122
173
  if (monthIndex === void 0) {
@@ -168,7 +219,7 @@ function normaliseTeamName(raw) {
168
219
  const trimmed = raw.trim();
169
220
  return ALIAS_MAP.get(trimmed.toLowerCase()) ?? trimmed;
170
221
  }
171
- var TEAM_ALIASES, AFL_SENIOR_TEAMS, ALIAS_MAP;
222
+ var TEAM_ALIASES, AFL_SENIOR_TEAMS, ALIAS_MAP, AFL_API_TEAM_IDS;
172
223
  var init_team_mapping = __esm({
173
224
  "src/lib/team-mapping.ts"() {
174
225
  "use strict";
@@ -241,6 +292,26 @@ var init_team_mapping = __esm({
241
292
  }
242
293
  return map;
243
294
  })();
295
+ AFL_API_TEAM_IDS = /* @__PURE__ */ new Map([
296
+ ["CD_T10", "Adelaide Crows"],
297
+ ["CD_T20", "Brisbane Lions"],
298
+ ["CD_T30", "Carlton"],
299
+ ["CD_T40", "Collingwood"],
300
+ ["CD_T50", "Essendon"],
301
+ ["CD_T60", "Fremantle"],
302
+ ["CD_T70", "Geelong Cats"],
303
+ ["CD_T1000", "Gold Coast Suns"],
304
+ ["CD_T1010", "GWS Giants"],
305
+ ["CD_T80", "Hawthorn"],
306
+ ["CD_T90", "Melbourne"],
307
+ ["CD_T100", "North Melbourne"],
308
+ ["CD_T110", "Port Adelaide"],
309
+ ["CD_T120", "Richmond"],
310
+ ["CD_T130", "St Kilda"],
311
+ ["CD_T160", "Sydney Swans"],
312
+ ["CD_T150", "West Coast Eagles"],
313
+ ["CD_T140", "Western Bulldogs"]
314
+ ]);
244
315
  }
245
316
  });
246
317
 
@@ -506,6 +577,14 @@ var init_footywire_player_stats = __esm({
506
577
  function inferRoundType(roundName) {
507
578
  return FINALS_PATTERN.test(roundName) ? "Finals" : "HomeAndAway";
508
579
  }
580
+ function finalsRoundNumber(headerText, lastHARound) {
581
+ const lower = headerText.toLowerCase();
582
+ if (lower.includes("qualifying") || lower.includes("elimination")) return lastHARound + 1;
583
+ if (lower.includes("semi")) return lastHARound + 2;
584
+ if (lower.includes("preliminary")) return lastHARound + 3;
585
+ if (lower.includes("grand")) return lastHARound + 4;
586
+ return lastHARound + 1;
587
+ }
509
588
  function toMatchStatus(raw) {
510
589
  switch (raw) {
511
590
  case "CONCLUDED":
@@ -595,6 +674,7 @@ function parseMatchList(html, year) {
595
674
  const $ = cheerio2.load(html);
596
675
  const results = [];
597
676
  let currentRound = 0;
677
+ let lastHARound = 0;
598
678
  let currentRoundType = "HomeAndAway";
599
679
  $("tr").each((_i, row) => {
600
680
  const roundHeader = $(row).find("td[colspan='7']");
@@ -604,6 +684,11 @@ function parseMatchList(html, year) {
604
684
  const roundMatch = /Round\s+(\d+)/i.exec(text);
605
685
  if (roundMatch?.[1]) {
606
686
  currentRound = Number.parseInt(roundMatch[1], 10);
687
+ if (currentRoundType === "HomeAndAway") {
688
+ lastHARound = currentRound;
689
+ }
690
+ } else if (currentRoundType === "Finals") {
691
+ currentRound = finalsRoundNumber(text, lastHARound);
607
692
  }
608
693
  return;
609
694
  }
@@ -674,6 +759,7 @@ function parseFixtureList(html, year) {
674
759
  const $ = cheerio2.load(html);
675
760
  const fixtures = [];
676
761
  let currentRound = 0;
762
+ let lastHARound = 0;
677
763
  let currentRoundType = "HomeAndAway";
678
764
  let gameNumber = 0;
679
765
  $("tr").each((_i, row) => {
@@ -684,6 +770,11 @@ function parseFixtureList(html, year) {
684
770
  const roundMatch = /Round\s+(\d+)/i.exec(text);
685
771
  if (roundMatch?.[1]) {
686
772
  currentRound = Number.parseInt(roundMatch[1], 10);
773
+ if (currentRoundType === "HomeAndAway") {
774
+ lastHARound = currentRound;
775
+ }
776
+ } else if (currentRoundType === "Finals") {
777
+ currentRound = finalsRoundNumber(text, lastHARound);
687
778
  }
688
779
  return;
689
780
  }
@@ -1431,7 +1522,14 @@ var init_validation = __esm({
1431
1522
  captain: z.boolean().optional(),
1432
1523
  playerJumperNumber: z.number().optional()
1433
1524
  }).passthrough();
1434
- statNum = z.number().nullable().optional();
1525
+ statNum = z.union([
1526
+ z.number(),
1527
+ z.string().transform((s) => {
1528
+ if (s === "" || s === "-") return null;
1529
+ const n = Number(s);
1530
+ return Number.isNaN(n) ? null : n;
1531
+ })
1532
+ ]).nullable().optional();
1435
1533
  PlayerGameStatsSchema = z.object({
1436
1534
  goals: statNum,
1437
1535
  behinds: statNum,
@@ -1509,8 +1607,8 @@ var init_validation = __esm({
1509
1607
  teamId: z.string(),
1510
1608
  playerStats: z.object({
1511
1609
  stats: PlayerGameStatsSchema,
1512
- timeOnGroundPercentage: z.number().nullable().optional()
1513
- }).passthrough()
1610
+ timeOnGroundPercentage: statNum
1611
+ }).passthrough().nullable().optional()
1514
1612
  }).passthrough();
1515
1613
  PlayerStatsListSchema = z.object({
1516
1614
  homeTeamPlayerStats: z.array(PlayerStatsItemSchema),
@@ -2221,12 +2319,14 @@ function toFixture(item, season, fallbackRoundNumber, competition) {
2221
2319
  async function fetchFixture(query) {
2222
2320
  const competition = query.competition ?? "AFLM";
2223
2321
  if (query.source === "squiggle") {
2322
+ if (competition === "AFLW") return err(aflwUnsupportedError("squiggle"));
2224
2323
  const client2 = new SquiggleClient();
2225
2324
  const result = await client2.fetchGames(query.season, query.round ?? void 0);
2226
2325
  if (!result.success) return result;
2227
2326
  return ok(transformSquiggleGamesToFixture(result.data.games, query.season));
2228
2327
  }
2229
2328
  if (query.source === "footywire") {
2329
+ if (competition === "AFLW") return err(aflwUnsupportedError("footywire"));
2230
2330
  const fwClient = new FootyWireClient();
2231
2331
  const result = await fwClient.fetchSeasonFixture(query.season);
2232
2332
  if (!result.success) return result;
@@ -2417,6 +2517,7 @@ function parseSeasonPage(html, year) {
2417
2517
  const results = [];
2418
2518
  let currentRound = 0;
2419
2519
  let currentRoundType = "HomeAndAway";
2520
+ let lastHARound = 0;
2420
2521
  let matchCounter = 0;
2421
2522
  $("table").each((_i, table) => {
2422
2523
  const $table = $(table);
@@ -2426,10 +2527,14 @@ function parseSeasonPage(html, year) {
2426
2527
  if (roundMatch?.[1] && border !== "1") {
2427
2528
  currentRound = Number.parseInt(roundMatch[1], 10);
2428
2529
  currentRoundType = inferRoundType(text);
2530
+ if (currentRoundType === "HomeAndAway") {
2531
+ lastHARound = currentRound;
2532
+ }
2429
2533
  return;
2430
2534
  }
2431
2535
  if (border !== "1" && inferRoundType(text) === "Finals") {
2432
2536
  currentRoundType = "Finals";
2537
+ currentRound = finalsRoundNumber(text, lastHARound);
2433
2538
  return;
2434
2539
  }
2435
2540
  if (border !== "1") return;
@@ -2939,6 +3044,7 @@ var init_ladder = __esm({
2939
3044
  async function fetchLadder(query) {
2940
3045
  const competition = query.competition ?? "AFLM";
2941
3046
  if (query.source === "squiggle") {
3047
+ if (competition === "AFLW") return err(aflwUnsupportedError("squiggle"));
2942
3048
  const client2 = new SquiggleClient();
2943
3049
  const result = await client2.fetchStandings(query.season, query.round ?? void 0);
2944
3050
  if (!result.success) return result;
@@ -2950,6 +3056,7 @@ async function fetchLadder(query) {
2950
3056
  });
2951
3057
  }
2952
3058
  if (query.source === "afl-tables") {
3059
+ if (competition === "AFLW") return err(aflwUnsupportedError("afl-tables"));
2953
3060
  const atClient = new AflTablesClient();
2954
3061
  const resultsResult = await atClient.fetchSeasonResults(query.season);
2955
3062
  if (!resultsResult.success) return resultsResult;
@@ -3114,6 +3221,7 @@ async function fetchMatchResults(query) {
3114
3221
  return ok(transformMatchItems(itemsResult.data, query.season, competition));
3115
3222
  }
3116
3223
  case "footywire": {
3224
+ if (competition === "AFLW") return err(aflwUnsupportedError("footywire"));
3117
3225
  const client = new FootyWireClient();
3118
3226
  const result = await client.fetchSeasonResults(query.season);
3119
3227
  if (!result.success) return result;
@@ -3123,6 +3231,7 @@ async function fetchMatchResults(query) {
3123
3231
  return result;
3124
3232
  }
3125
3233
  case "afl-tables": {
3234
+ if (competition === "AFLW") return err(aflwUnsupportedError("afl-tables"));
3126
3235
  const client = new AflTablesClient();
3127
3236
  const result = await client.fetchSeasonResults(query.season);
3128
3237
  if (!result.success) return result;
@@ -3132,6 +3241,7 @@ async function fetchMatchResults(query) {
3132
3241
  return result;
3133
3242
  }
3134
3243
  case "squiggle": {
3244
+ if (competition === "AFLW") return err(aflwUnsupportedError("squiggle"));
3135
3245
  const client = new SquiggleClient();
3136
3246
  const result = await client.fetchGames(query.season, query.round ?? void 0, 100);
3137
3247
  if (!result.success) return result;
@@ -3170,7 +3280,7 @@ async function resolveTeamId(client, teamName, competition) {
3170
3280
  async function fetchFromAflApi(query) {
3171
3281
  const client = new AflApiClient();
3172
3282
  const competition = query.competition ?? "AFLM";
3173
- const season = query.season ?? (/* @__PURE__ */ new Date()).getFullYear();
3283
+ const season = query.season ?? resolveDefaultSeason(competition);
3174
3284
  const [teamIdResult, seasonResult] = await Promise.all([
3175
3285
  resolveTeamId(client, query.team, competition),
3176
3286
  client.resolveCompSeason(competition, season)
@@ -3193,8 +3303,8 @@ async function fetchFromAflApi(query) {
3193
3303
  jumperNumber: p.jumperNumber ?? null,
3194
3304
  position: p.position ?? null,
3195
3305
  dateOfBirth: p.player.dateOfBirth ?? null,
3196
- heightCm: p.player.heightInCm ?? null,
3197
- weightKg: p.player.weightInKg ?? null,
3306
+ heightCm: p.player.heightInCm || null,
3307
+ weightKg: p.player.weightInKg || null,
3198
3308
  gamesPlayed: null,
3199
3309
  goals: null,
3200
3310
  draftYear: p.player.draftYear ? Number.parseInt(p.player.draftYear, 10) || null : null,
@@ -3208,8 +3318,9 @@ async function fetchFromAflApi(query) {
3208
3318
  return ok(players);
3209
3319
  }
3210
3320
  async function fetchFromFootyWire(query) {
3211
- const client = new FootyWireClient();
3212
3321
  const competition = query.competition ?? "AFLM";
3322
+ if (competition === "AFLW") return err(aflwUnsupportedError("footywire"));
3323
+ const client = new FootyWireClient();
3213
3324
  const teamName = normaliseTeamName(query.team);
3214
3325
  const result = await client.fetchPlayerList(teamName);
3215
3326
  if (!result.success) return result;
@@ -3221,8 +3332,9 @@ async function fetchFromFootyWire(query) {
3221
3332
  return ok(players);
3222
3333
  }
3223
3334
  async function fetchFromAflTables(query) {
3224
- const client = new AflTablesClient();
3225
3335
  const competition = query.competition ?? "AFLM";
3336
+ if (competition === "AFLW") return err(aflwUnsupportedError("afl-tables"));
3337
+ const client = new AflTablesClient();
3226
3338
  const teamName = normaliseTeamName(query.team);
3227
3339
  const result = await client.fetchPlayerList(teamName);
3228
3340
  if (!result.success) return result;
@@ -3253,6 +3365,7 @@ async function fetchPlayerDetails(query) {
3253
3365
  var init_player_details = __esm({
3254
3366
  "src/api/player-details.ts"() {
3255
3367
  "use strict";
3368
+ init_date_utils();
3256
3369
  init_errors();
3257
3370
  init_result();
3258
3371
  init_team_mapping();
@@ -3268,80 +3381,82 @@ function toNullable(value) {
3268
3381
  }
3269
3382
  function transformOne(item, matchId, season, roundNumber, competition, source, teamIdMap) {
3270
3383
  const inner = item.player.player.player;
3271
- const stats = item.playerStats.stats;
3272
- const clearances = stats.clearances;
3384
+ const stats = item.playerStats?.stats;
3385
+ const clearances = stats?.clearances;
3273
3386
  return {
3274
3387
  matchId,
3275
3388
  season,
3276
3389
  roundNumber,
3277
- team: normaliseTeamName(teamIdMap?.get(item.teamId) ?? item.teamId),
3390
+ team: normaliseTeamName(
3391
+ teamIdMap?.get(item.teamId) ?? AFL_API_TEAM_IDS.get(item.teamId) ?? item.teamId
3392
+ ),
3278
3393
  competition,
3279
3394
  playerId: inner.playerId,
3280
3395
  givenName: inner.playerName.givenName,
3281
3396
  surname: inner.playerName.surname,
3282
3397
  displayName: `${inner.playerName.givenName} ${inner.playerName.surname}`,
3283
3398
  jumperNumber: item.player.jumperNumber ?? null,
3284
- kicks: toNullable(stats.kicks),
3285
- handballs: toNullable(stats.handballs),
3286
- disposals: toNullable(stats.disposals),
3287
- marks: toNullable(stats.marks),
3288
- goals: toNullable(stats.goals),
3289
- behinds: toNullable(stats.behinds),
3290
- tackles: toNullable(stats.tackles),
3291
- hitouts: toNullable(stats.hitouts),
3292
- freesFor: toNullable(stats.freesFor),
3293
- freesAgainst: toNullable(stats.freesAgainst),
3294
- contestedPossessions: toNullable(stats.contestedPossessions),
3295
- uncontestedPossessions: toNullable(stats.uncontestedPossessions),
3296
- contestedMarks: toNullable(stats.contestedMarks),
3297
- intercepts: toNullable(stats.intercepts),
3399
+ kicks: toNullable(stats?.kicks),
3400
+ handballs: toNullable(stats?.handballs),
3401
+ disposals: toNullable(stats?.disposals),
3402
+ marks: toNullable(stats?.marks),
3403
+ goals: toNullable(stats?.goals),
3404
+ behinds: toNullable(stats?.behinds),
3405
+ tackles: toNullable(stats?.tackles),
3406
+ hitouts: toNullable(stats?.hitouts),
3407
+ freesFor: toNullable(stats?.freesFor),
3408
+ freesAgainst: toNullable(stats?.freesAgainst),
3409
+ contestedPossessions: toNullable(stats?.contestedPossessions),
3410
+ uncontestedPossessions: toNullable(stats?.uncontestedPossessions),
3411
+ contestedMarks: toNullable(stats?.contestedMarks),
3412
+ intercepts: toNullable(stats?.intercepts),
3298
3413
  centreClearances: toNullable(clearances?.centreClearances),
3299
3414
  stoppageClearances: toNullable(clearances?.stoppageClearances),
3300
3415
  totalClearances: toNullable(clearances?.totalClearances),
3301
- inside50s: toNullable(stats.inside50s),
3302
- rebound50s: toNullable(stats.rebound50s),
3303
- clangers: toNullable(stats.clangers),
3304
- turnovers: toNullable(stats.turnovers),
3305
- onePercenters: toNullable(stats.onePercenters),
3306
- bounces: toNullable(stats.bounces),
3307
- goalAssists: toNullable(stats.goalAssists),
3308
- disposalEfficiency: toNullable(stats.disposalEfficiency),
3309
- metresGained: toNullable(stats.metresGained),
3310
- goalAccuracy: toNullable(stats.goalAccuracy),
3311
- marksInside50: toNullable(stats.marksInside50),
3312
- tacklesInside50: toNullable(stats.tacklesInside50),
3313
- shotsAtGoal: toNullable(stats.shotsAtGoal),
3314
- scoreInvolvements: toNullable(stats.scoreInvolvements),
3315
- totalPossessions: toNullable(stats.totalPossessions),
3316
- timeOnGroundPercentage: toNullable(item.playerStats.timeOnGroundPercentage),
3317
- ratingPoints: toNullable(stats.ratingPoints),
3318
- dreamTeamPoints: toNullable(stats.dreamTeamPoints),
3319
- effectiveDisposals: toNullable(stats.extendedStats?.effectiveDisposals),
3320
- effectiveKicks: toNullable(stats.extendedStats?.effectiveKicks),
3321
- kickEfficiency: toNullable(stats.extendedStats?.kickEfficiency),
3322
- kickToHandballRatio: toNullable(stats.extendedStats?.kickToHandballRatio),
3323
- pressureActs: toNullable(stats.extendedStats?.pressureActs),
3324
- defHalfPressureActs: toNullable(stats.extendedStats?.defHalfPressureActs),
3325
- spoils: toNullable(stats.extendedStats?.spoils),
3326
- hitoutsToAdvantage: toNullable(stats.extendedStats?.hitoutsToAdvantage),
3327
- hitoutWinPercentage: toNullable(stats.extendedStats?.hitoutWinPercentage),
3328
- hitoutToAdvantageRate: toNullable(stats.extendedStats?.hitoutToAdvantageRate),
3329
- groundBallGets: toNullable(stats.extendedStats?.groundBallGets),
3330
- f50GroundBallGets: toNullable(stats.extendedStats?.f50GroundBallGets),
3331
- interceptMarks: toNullable(stats.extendedStats?.interceptMarks),
3332
- marksOnLead: toNullable(stats.extendedStats?.marksOnLead),
3333
- contestedPossessionRate: toNullable(stats.extendedStats?.contestedPossessionRate),
3334
- contestOffOneOnOnes: toNullable(stats.extendedStats?.contestOffOneOnOnes),
3335
- contestOffWins: toNullable(stats.extendedStats?.contestOffWins),
3336
- contestOffWinsPercentage: toNullable(stats.extendedStats?.contestOffWinsPercentage),
3337
- contestDefOneOnOnes: toNullable(stats.extendedStats?.contestDefOneOnOnes),
3338
- contestDefLosses: toNullable(stats.extendedStats?.contestDefLosses),
3339
- contestDefLossPercentage: toNullable(stats.extendedStats?.contestDefLossPercentage),
3340
- centreBounceAttendances: toNullable(stats.extendedStats?.centreBounceAttendances),
3341
- kickins: toNullable(stats.extendedStats?.kickins),
3342
- kickinsPlayon: toNullable(stats.extendedStats?.kickinsPlayon),
3343
- ruckContests: toNullable(stats.extendedStats?.ruckContests),
3344
- scoreLaunches: toNullable(stats.extendedStats?.scoreLaunches),
3416
+ inside50s: toNullable(stats?.inside50s),
3417
+ rebound50s: toNullable(stats?.rebound50s),
3418
+ clangers: toNullable(stats?.clangers),
3419
+ turnovers: toNullable(stats?.turnovers),
3420
+ onePercenters: toNullable(stats?.onePercenters),
3421
+ bounces: toNullable(stats?.bounces),
3422
+ goalAssists: toNullable(stats?.goalAssists),
3423
+ disposalEfficiency: toNullable(stats?.disposalEfficiency),
3424
+ metresGained: toNullable(stats?.metresGained),
3425
+ goalAccuracy: toNullable(stats?.goalAccuracy),
3426
+ marksInside50: toNullable(stats?.marksInside50),
3427
+ tacklesInside50: toNullable(stats?.tacklesInside50),
3428
+ shotsAtGoal: toNullable(stats?.shotsAtGoal),
3429
+ scoreInvolvements: toNullable(stats?.scoreInvolvements),
3430
+ totalPossessions: toNullable(stats?.totalPossessions),
3431
+ timeOnGroundPercentage: toNullable(item.playerStats?.timeOnGroundPercentage),
3432
+ ratingPoints: toNullable(stats?.ratingPoints),
3433
+ dreamTeamPoints: toNullable(stats?.dreamTeamPoints),
3434
+ effectiveDisposals: toNullable(stats?.extendedStats?.effectiveDisposals),
3435
+ effectiveKicks: toNullable(stats?.extendedStats?.effectiveKicks),
3436
+ kickEfficiency: toNullable(stats?.extendedStats?.kickEfficiency),
3437
+ kickToHandballRatio: toNullable(stats?.extendedStats?.kickToHandballRatio),
3438
+ pressureActs: toNullable(stats?.extendedStats?.pressureActs),
3439
+ defHalfPressureActs: toNullable(stats?.extendedStats?.defHalfPressureActs),
3440
+ spoils: toNullable(stats?.extendedStats?.spoils),
3441
+ hitoutsToAdvantage: toNullable(stats?.extendedStats?.hitoutsToAdvantage),
3442
+ hitoutWinPercentage: toNullable(stats?.extendedStats?.hitoutWinPercentage),
3443
+ hitoutToAdvantageRate: toNullable(stats?.extendedStats?.hitoutToAdvantageRate),
3444
+ groundBallGets: toNullable(stats?.extendedStats?.groundBallGets),
3445
+ f50GroundBallGets: toNullable(stats?.extendedStats?.f50GroundBallGets),
3446
+ interceptMarks: toNullable(stats?.extendedStats?.interceptMarks),
3447
+ marksOnLead: toNullable(stats?.extendedStats?.marksOnLead),
3448
+ contestedPossessionRate: toNullable(stats?.extendedStats?.contestedPossessionRate),
3449
+ contestOffOneOnOnes: toNullable(stats?.extendedStats?.contestOffOneOnOnes),
3450
+ contestOffWins: toNullable(stats?.extendedStats?.contestOffWins),
3451
+ contestOffWinsPercentage: toNullable(stats?.extendedStats?.contestOffWinsPercentage),
3452
+ contestDefOneOnOnes: toNullable(stats?.extendedStats?.contestDefOneOnOnes),
3453
+ contestDefLosses: toNullable(stats?.extendedStats?.contestDefLosses),
3454
+ contestDefLossPercentage: toNullable(stats?.extendedStats?.contestDefLossPercentage),
3455
+ centreBounceAttendances: toNullable(stats?.extendedStats?.centreBounceAttendances),
3456
+ kickins: toNullable(stats?.extendedStats?.kickins),
3457
+ kickinsPlayon: toNullable(stats?.extendedStats?.kickinsPlayon),
3458
+ ruckContests: toNullable(stats?.extendedStats?.ruckContests),
3459
+ scoreLaunches: toNullable(stats?.extendedStats?.scoreLaunches),
3345
3460
  source
3346
3461
  };
3347
3462
  }
@@ -3430,6 +3545,7 @@ async function fetchPlayerStats(query) {
3430
3545
  return ok(allStats);
3431
3546
  }
3432
3547
  case "footywire": {
3548
+ if (competition === "AFLW") return err(aflwUnsupportedError("footywire"));
3433
3549
  const fwClient = new FootyWireClient();
3434
3550
  const idsResult = await fwClient.fetchSeasonMatchIds(query.season);
3435
3551
  if (!idsResult.success) return idsResult;
@@ -3459,6 +3575,7 @@ async function fetchPlayerStats(query) {
3459
3575
  return ok(allStats);
3460
3576
  }
3461
3577
  case "afl-tables": {
3578
+ if (competition === "AFLW") return err(aflwUnsupportedError("afl-tables"));
3462
3579
  const atClient = new AflTablesClient();
3463
3580
  const atResult = await atClient.fetchSeasonPlayerStats(query.season);
3464
3581
  if (!atResult.success) return atResult;
@@ -3494,7 +3611,37 @@ async function fetchTeamStats(query) {
3494
3611
  }
3495
3612
  case "afl-tables": {
3496
3613
  const client = new AflTablesClient();
3497
- return client.fetchTeamStats(query.season);
3614
+ const statsResult = await client.fetchTeamStats(query.season);
3615
+ if (!statsResult.success) return statsResult;
3616
+ const needsGp = statsResult.data.some((e) => e.gamesPlayed === 0);
3617
+ const gpMap = /* @__PURE__ */ new Map();
3618
+ if (needsGp) {
3619
+ const resultsResult = await client.fetchSeasonResults(query.season);
3620
+ if (resultsResult.success) {
3621
+ for (const m of resultsResult.data) {
3622
+ gpMap.set(m.homeTeam, (gpMap.get(m.homeTeam) ?? 0) + 1);
3623
+ gpMap.set(m.awayTeam, (gpMap.get(m.awayTeam) ?? 0) + 1);
3624
+ }
3625
+ }
3626
+ }
3627
+ const enriched = statsResult.data.map((entry) => ({
3628
+ ...entry,
3629
+ gamesPlayed: gpMap.get(entry.team) ?? entry.gamesPlayed
3630
+ }));
3631
+ if (summaryType === "averages") {
3632
+ return ok(
3633
+ enriched.map((entry) => ({
3634
+ ...entry,
3635
+ stats: Object.fromEntries(
3636
+ Object.entries(entry.stats).map(([k, v]) => [
3637
+ k,
3638
+ entry.gamesPlayed > 0 ? +(v / entry.gamesPlayed).toFixed(1) : 0
3639
+ ])
3640
+ )
3641
+ }))
3642
+ );
3643
+ }
3644
+ return ok(enriched);
3498
3645
  }
3499
3646
  case "afl-api":
3500
3647
  case "squiggle":
@@ -3522,19 +3669,30 @@ var init_team_stats = __esm({
3522
3669
  function teamTypeForComp(comp) {
3523
3670
  return comp === "AFLW" ? "WOMEN" : "MEN";
3524
3671
  }
3525
- async function fetchTeams(query) {
3526
- const client = new AflApiClient();
3527
- const teamType = query?.teamType ?? teamTypeForComp(query?.competition ?? "AFLM");
3528
- const result = await client.fetchTeams(teamType);
3529
- if (!result.success) return result;
3530
- const competition = query?.competition ?? "AFLM";
3531
- const teams = result.data.map((t) => ({
3672
+ function toTeams(data, competition) {
3673
+ return data.map((t) => ({
3532
3674
  teamId: String(t.id),
3533
3675
  name: normaliseTeamName(t.name),
3534
3676
  abbreviation: t.abbreviation ?? "",
3535
3677
  competition
3536
3678
  })).filter((t) => AFL_SENIOR_TEAMS.has(t.name));
3537
- return ok(teams);
3679
+ }
3680
+ async function fetchTeams(query) {
3681
+ const client = new AflApiClient();
3682
+ if (!query?.competition && !query?.teamType) {
3683
+ const [menResult, womenResult] = await Promise.all([
3684
+ client.fetchTeams("MEN"),
3685
+ client.fetchTeams("WOMEN")
3686
+ ]);
3687
+ if (!menResult.success) return menResult;
3688
+ if (!womenResult.success) return womenResult;
3689
+ return ok([...toTeams(menResult.data, "AFLM"), ...toTeams(womenResult.data, "AFLW")]);
3690
+ }
3691
+ const competition = query?.competition ?? "AFLM";
3692
+ const teamType = query?.teamType ?? teamTypeForComp(competition);
3693
+ const result = await client.fetchTeams(teamType);
3694
+ if (!result.success) return result;
3695
+ return ok(toTeams(result.data, competition));
3538
3696
  }
3539
3697
  async function fetchSquad(query) {
3540
3698
  const client = new AflApiClient();
@@ -3555,8 +3713,8 @@ async function fetchSquad(query) {
3555
3713
  jumperNumber: p.jumperNumber ?? null,
3556
3714
  position: p.position ?? null,
3557
3715
  dateOfBirth: p.player.dateOfBirth ? new Date(p.player.dateOfBirth) : null,
3558
- heightCm: p.player.heightInCm ?? null,
3559
- weightKg: p.player.weightInKg ?? null,
3716
+ heightCm: p.player.heightInCm || null,
3717
+ weightKg: p.player.weightInKg || null,
3560
3718
  draftYear: p.player.draftYear ? Number.parseInt(p.player.draftYear, 10) || null : null,
3561
3719
  draftPosition: p.player.draftPosition ? Number.parseInt(p.player.draftPosition, 10) || null : null,
3562
3720
  draftType: p.player.draftType ?? null,
@@ -3897,10 +4055,6 @@ function validateOptionalSeason(raw) {
3897
4055
  if (raw != null) return validateSeason(raw);
3898
4056
  return void 0;
3899
4057
  }
3900
- function resolveDefaultSeason(competition = "AFLM") {
3901
- const year = (/* @__PURE__ */ new Date()).getFullYear();
3902
- return competition === "AFLW" ? year - 1 : year;
3903
- }
3904
4058
  function validateRound(raw) {
3905
4059
  const round = Number(raw);
3906
4060
  if (Number.isNaN(round) || !Number.isInteger(round) || round < 0) {
@@ -3979,6 +4133,7 @@ var init_validation2 = __esm({
3979
4133
  "src/cli/validation.ts"() {
3980
4134
  "use strict";
3981
4135
  init_team_mapping();
4136
+ init_date_utils();
3982
4137
  VALID_SOURCES = ["afl-api", "footywire", "afl-tables", "squiggle"];
3983
4138
  VALID_COMPETITIONS = ["AFLM", "AFLW"];
3984
4139
  VALID_FORMATS = ["table", "json", "csv"];
@@ -3996,6 +4151,7 @@ var init_matches = __esm({
3996
4151
  "src/cli/commands/matches.ts"() {
3997
4152
  "use strict";
3998
4153
  init_index();
4154
+ init_error_boundary();
3999
4155
  init_flags();
4000
4156
  init_formatters();
4001
4157
  init_ui();
@@ -4021,7 +4177,7 @@ var init_matches = __esm({
4021
4177
  ...COMPETITION_FLAG,
4022
4178
  ...OUTPUT_FLAGS
4023
4179
  },
4024
- async run({ args }) {
4180
+ run: withErrorBoundary(async ({ args }) => {
4025
4181
  const season = validateSeason(args.season);
4026
4182
  const round = args.round ? validateRound(args.round) : void 0;
4027
4183
  const source = validateSource(args.source);
@@ -4044,7 +4200,7 @@ var init_matches = __esm({
4044
4200
  columns: DEFAULT_COLUMNS
4045
4201
  };
4046
4202
  console.log(formatOutput(data, formatOptions));
4047
- }
4203
+ })
4048
4204
  });
4049
4205
  }
4050
4206
  });
@@ -4259,6 +4415,7 @@ var init_stats = __esm({
4259
4415
  init_index();
4260
4416
  init_fuzzy();
4261
4417
  init_afl_api();
4418
+ init_error_boundary();
4262
4419
  init_flags();
4263
4420
  init_formatters();
4264
4421
  init_resolvers();
@@ -4288,7 +4445,7 @@ var init_stats = __esm({
4288
4445
  ...PLAYER_FLAG,
4289
4446
  ...OUTPUT_FLAGS
4290
4447
  },
4291
- async run({ args }) {
4448
+ run: withErrorBoundary(async ({ args }) => {
4292
4449
  const season = validateSeason(args.season);
4293
4450
  const round = args.round ? validateRound(args.round) : void 0;
4294
4451
  const source = validateSource(args.source);
@@ -4331,7 +4488,7 @@ var init_stats = __esm({
4331
4488
  columns: DEFAULT_COLUMNS2
4332
4489
  };
4333
4490
  console.log(formatOutput(data, formatOptions));
4334
- }
4491
+ })
4335
4492
  });
4336
4493
  }
4337
4494
  });
@@ -4347,6 +4504,7 @@ var init_fixture2 = __esm({
4347
4504
  "src/cli/commands/fixture.ts"() {
4348
4505
  "use strict";
4349
4506
  init_index();
4507
+ init_error_boundary();
4350
4508
  init_flags();
4351
4509
  init_formatters();
4352
4510
  init_ui();
@@ -4370,7 +4528,7 @@ var init_fixture2 = __esm({
4370
4528
  ...COMPETITION_FLAG,
4371
4529
  ...OUTPUT_FLAGS
4372
4530
  },
4373
- async run({ args }) {
4531
+ run: withErrorBoundary(async ({ args }) => {
4374
4532
  const season = validateSeason(args.season);
4375
4533
  const round = args.round ? validateRound(args.round) : void 0;
4376
4534
  const source = validateSource(args.source);
@@ -4393,7 +4551,7 @@ var init_fixture2 = __esm({
4393
4551
  columns: DEFAULT_COLUMNS3
4394
4552
  };
4395
4553
  console.log(formatOutput(data, formatOptions));
4396
- }
4554
+ })
4397
4555
  });
4398
4556
  }
4399
4557
  });
@@ -4409,6 +4567,7 @@ var init_ladder3 = __esm({
4409
4567
  "src/cli/commands/ladder.ts"() {
4410
4568
  "use strict";
4411
4569
  init_index();
4570
+ init_error_boundary();
4412
4571
  init_flags();
4413
4572
  init_formatters();
4414
4573
  init_ui();
@@ -4434,7 +4593,7 @@ var init_ladder3 = __esm({
4434
4593
  ...COMPETITION_FLAG,
4435
4594
  ...OUTPUT_FLAGS
4436
4595
  },
4437
- async run({ args }) {
4596
+ run: withErrorBoundary(async ({ args }) => {
4438
4597
  const season = validateSeason(args.season);
4439
4598
  const round = args.round ? validateRound(args.round) : void 0;
4440
4599
  const source = validateSource(args.source);
@@ -4459,7 +4618,7 @@ var init_ladder3 = __esm({
4459
4618
  columns: DEFAULT_COLUMNS4
4460
4619
  };
4461
4620
  console.log(formatOutput(data.entries, formatOptions));
4462
- }
4621
+ })
4463
4622
  });
4464
4623
  }
4465
4624
  });
@@ -4498,6 +4657,7 @@ var init_lineup3 = __esm({
4498
4657
  "use strict";
4499
4658
  init_index();
4500
4659
  init_afl_api();
4660
+ init_error_boundary();
4501
4661
  init_flags();
4502
4662
  init_formatters();
4503
4663
  init_resolvers();
@@ -4524,7 +4684,7 @@ var init_lineup3 = __esm({
4524
4684
  ...COMPETITION_FLAG,
4525
4685
  ...OUTPUT_FLAGS
4526
4686
  },
4527
- async run({ args }) {
4687
+ run: withErrorBoundary(async ({ args }) => {
4528
4688
  const season = validateSeason(args.season);
4529
4689
  const round = validateRound(args.round);
4530
4690
  const source = validateSource(args.source);
@@ -4561,7 +4721,7 @@ var init_lineup3 = __esm({
4561
4721
  } else {
4562
4722
  console.log(formatOutput(flattenLineups(data), formatOptions));
4563
4723
  }
4564
- }
4724
+ })
4565
4725
  });
4566
4726
  }
4567
4727
  });
@@ -4577,6 +4737,7 @@ var init_squad = __esm({
4577
4737
  "src/cli/commands/squad.ts"() {
4578
4738
  "use strict";
4579
4739
  init_index();
4740
+ init_error_boundary();
4580
4741
  init_flags();
4581
4742
  init_formatters();
4582
4743
  init_resolvers();
@@ -4600,7 +4761,7 @@ var init_squad = __esm({
4600
4761
  ...COMPETITION_FLAG,
4601
4762
  ...OUTPUT_FLAGS
4602
4763
  },
4603
- async run({ args }) {
4764
+ run: withErrorBoundary(async ({ args }) => {
4604
4765
  const season = validateSeason(args.season);
4605
4766
  const competition = validateCompetition(args.competition);
4606
4767
  const format = validateFormat(args.format);
@@ -4629,7 +4790,7 @@ var init_squad = __esm({
4629
4790
  columns: DEFAULT_COLUMNS6
4630
4791
  };
4631
4792
  console.log(formatOutput(data.players, formatOptions));
4632
- }
4793
+ })
4633
4794
  });
4634
4795
  }
4635
4796
  });
@@ -4645,6 +4806,7 @@ var init_teams2 = __esm({
4645
4806
  "src/cli/commands/teams.ts"() {
4646
4807
  "use strict";
4647
4808
  init_index();
4809
+ init_error_boundary();
4648
4810
  init_flags();
4649
4811
  init_formatters();
4650
4812
  init_ui();
@@ -4665,7 +4827,7 @@ var init_teams2 = __esm({
4665
4827
  "team-type": { type: "string", description: "Team type filter" },
4666
4828
  ...OUTPUT_FLAGS
4667
4829
  },
4668
- async run({ args }) {
4830
+ run: withErrorBoundary(async ({ args }) => {
4669
4831
  const competition = validateOptionalCompetition(args.competition);
4670
4832
  const format = validateFormat(args.format);
4671
4833
  const result = await withSpinner(
@@ -4690,7 +4852,7 @@ var init_teams2 = __esm({
4690
4852
  columns: DEFAULT_COLUMNS7
4691
4853
  };
4692
4854
  console.log(formatOutput(data, formatOptions));
4693
- }
4855
+ })
4694
4856
  });
4695
4857
  }
4696
4858
  });
@@ -4704,14 +4866,19 @@ import { defineCommand as defineCommand8 } from "citty";
4704
4866
  function flattenEntries(data) {
4705
4867
  return data.map((entry) => {
4706
4868
  const { stats, ...rest } = entry;
4707
- return { ...rest, ...stats };
4869
+ const normalised = {};
4870
+ for (const [key, value] of Object.entries(stats)) {
4871
+ normalised[AFL_TABLES_KEY_MAP[key] ?? key] = value;
4872
+ }
4873
+ return { ...rest, ...normalised };
4708
4874
  });
4709
4875
  }
4710
- var DEFAULT_COLUMNS8, teamStatsCommand;
4876
+ var DEFAULT_COLUMNS8, AFL_TABLES_KEY_MAP, teamStatsCommand;
4711
4877
  var init_team_stats2 = __esm({
4712
4878
  "src/cli/commands/team-stats.ts"() {
4713
4879
  "use strict";
4714
4880
  init_index();
4881
+ init_error_boundary();
4715
4882
  init_flags();
4716
4883
  init_formatters();
4717
4884
  init_ui();
@@ -4728,6 +4895,53 @@ var init_team_stats2 = __esm({
4728
4895
  { key: "T", label: "T", maxWidth: 6 },
4729
4896
  { key: "I50", label: "I50", maxWidth: 6 }
4730
4897
  ];
4898
+ AFL_TABLES_KEY_MAP = {
4899
+ KI_for: "K",
4900
+ MK_for: "M",
4901
+ HB_for: "HB",
4902
+ DI_for: "D",
4903
+ GL_for: "G",
4904
+ BH_for: "B",
4905
+ HO_for: "HO",
4906
+ TK_for: "T",
4907
+ RB_for: "RB",
4908
+ IF_for: "IF",
4909
+ CL_for: "CL",
4910
+ CG_for: "CG",
4911
+ FF_for: "FF",
4912
+ BR_for: "BR",
4913
+ CP_for: "CP",
4914
+ UP_for: "UP",
4915
+ CM_for: "CM",
4916
+ MI_for: "MI",
4917
+ "1%_for": "1%",
4918
+ BO_for: "BO",
4919
+ GA_for: "GA",
4920
+ I50_for: "I50",
4921
+ // "against" variants
4922
+ KI_against: "K_against",
4923
+ MK_against: "M_against",
4924
+ HB_against: "HB_against",
4925
+ DI_against: "D_against",
4926
+ GL_against: "G_against",
4927
+ BH_against: "B_against",
4928
+ HO_against: "HO_against",
4929
+ TK_against: "T_against",
4930
+ RB_against: "RB_against",
4931
+ IF_against: "IF_against",
4932
+ CL_against: "CL_against",
4933
+ CG_against: "CG_against",
4934
+ FF_against: "FF_against",
4935
+ BR_against: "BR_against",
4936
+ CP_against: "CP_against",
4937
+ UP_against: "UP_against",
4938
+ CM_against: "CM_against",
4939
+ MI_against: "MI_against",
4940
+ "1%_against": "1%_against",
4941
+ BO_against: "BO_against",
4942
+ GA_against: "GA_against",
4943
+ I50_against: "I50_against"
4944
+ };
4731
4945
  teamStatsCommand = defineCommand8({
4732
4946
  meta: {
4733
4947
  name: "team-stats",
@@ -4743,7 +4957,7 @@ var init_team_stats2 = __esm({
4743
4957
  summary: { type: "string", description: "Summary type: totals or averages", default: "totals" },
4744
4958
  ...OUTPUT_FLAGS
4745
4959
  },
4746
- async run({ args }) {
4960
+ run: withErrorBoundary(async ({ args }) => {
4747
4961
  const season = validateSeason(args.season);
4748
4962
  const source = validateSource(args.source);
4749
4963
  const format = validateFormat(args.format);
@@ -4766,7 +4980,7 @@ var init_team_stats2 = __esm({
4766
4980
  columns: DEFAULT_COLUMNS8
4767
4981
  };
4768
4982
  console.log(formatOutput(flat, formatOptions));
4769
- }
4983
+ })
4770
4984
  });
4771
4985
  }
4772
4986
  });
@@ -4782,6 +4996,7 @@ var init_player_details2 = __esm({
4782
4996
  "src/cli/commands/player-details.ts"() {
4783
4997
  "use strict";
4784
4998
  init_index();
4999
+ init_error_boundary();
4785
5000
  init_flags();
4786
5001
  init_formatters();
4787
5002
  init_resolvers();
@@ -4812,7 +5027,7 @@ var init_player_details2 = __esm({
4812
5027
  ...COMPETITION_FLAG,
4813
5028
  ...OUTPUT_FLAGS
4814
5029
  },
4815
- async run({ args }) {
5030
+ run: withErrorBoundary(async ({ args }) => {
4816
5031
  const source = validateSource(args.source);
4817
5032
  const competition = validateCompetition(args.competition);
4818
5033
  const format = validateFormat(args.format);
@@ -4835,7 +5050,7 @@ var init_player_details2 = __esm({
4835
5050
  columns: DEFAULT_COLUMNS9
4836
5051
  };
4837
5052
  console.log(formatOutput(data, formatOptions));
4838
- }
5053
+ })
4839
5054
  });
4840
5055
  }
4841
5056
  });
@@ -4851,6 +5066,7 @@ var init_coaches_votes2 = __esm({
4851
5066
  "src/cli/commands/coaches-votes.ts"() {
4852
5067
  "use strict";
4853
5068
  init_index();
5069
+ init_error_boundary();
4854
5070
  init_flags();
4855
5071
  init_formatters();
4856
5072
  init_resolvers();
@@ -4876,7 +5092,7 @@ var init_coaches_votes2 = __esm({
4876
5092
  ...TEAM_FLAG,
4877
5093
  ...OUTPUT_FLAGS
4878
5094
  },
4879
- async run({ args }) {
5095
+ run: withErrorBoundary(async ({ args }) => {
4880
5096
  const season = validateSeason(args.season);
4881
5097
  const round = args.round ? validateRound(args.round) : void 0;
4882
5098
  const competition = validateCompetition(args.competition);
@@ -4901,7 +5117,7 @@ var init_coaches_votes2 = __esm({
4901
5117
  columns: DEFAULT_COLUMNS10
4902
5118
  };
4903
5119
  console.log(formatOutput(data, formatOptions));
4904
- }
5120
+ })
4905
5121
  });
4906
5122
  }
4907
5123
  });
@@ -4909,37 +5125,34 @@ var init_coaches_votes2 = __esm({
4909
5125
  // src/cli.ts
4910
5126
  import { defineCommand as defineCommand11, runMain } from "citty";
4911
5127
 
4912
- // src/cli/error-boundary.ts
4913
- init_errors();
4914
- import pc from "picocolors";
4915
- function formatError(error) {
4916
- if (error instanceof ValidationError && error.issues) {
4917
- const issueLines = error.issues.map((i) => ` ${pc.yellow(i.path)}: ${i.message}`);
4918
- return `${pc.red("Validation error:")}
4919
- ${issueLines.join("\n")}`;
4920
- }
4921
- if (error instanceof AflApiError) {
4922
- const status = error.statusCode ? ` (HTTP ${error.statusCode})` : "";
4923
- return `${pc.red("AFL API error:")} ${error.message}${status}`;
4924
- }
4925
- if (error instanceof ScrapeError) {
4926
- const source = error.source ? ` [${error.source}]` : "";
4927
- return `${pc.red("Scrape error:")} ${error.message}${source}`;
4928
- }
4929
- if (error instanceof UnsupportedSourceError) {
4930
- return `${pc.red("Unsupported source:")} ${error.message}`;
4931
- }
4932
- if (error instanceof Error) {
4933
- return `${pc.red("Error:")} ${error.message}`;
5128
+ // src/cli/alias-resolution.ts
5129
+ var SHORT_TO_LONG = {
5130
+ "-s": "--season",
5131
+ "-r": "--round",
5132
+ "-c": "--competition",
5133
+ "-j": "--json",
5134
+ "-t": "--team",
5135
+ "-p": "--player"
5136
+ };
5137
+ function resolveAliases() {
5138
+ for (let i = 0; i < process.argv.length; i++) {
5139
+ const arg = process.argv[i];
5140
+ if (arg != null) {
5141
+ const long = SHORT_TO_LONG[arg];
5142
+ if (long) {
5143
+ process.argv[i] = long;
5144
+ }
5145
+ }
4934
5146
  }
4935
- return `${pc.red("Error:")} ${String(error)}`;
4936
5147
  }
4937
5148
 
4938
5149
  // src/cli.ts
5150
+ init_error_boundary();
5151
+ resolveAliases();
4939
5152
  var main = defineCommand11({
4940
5153
  meta: {
4941
5154
  name: "fitzroy",
4942
- version: "1.2.0",
5155
+ version: "1.3.0",
4943
5156
  description: "CLI for fetching AFL data \u2014 match results, player stats, fixtures, ladders, and more"
4944
5157
  },
4945
5158
  subCommands: {