cricinfo-cli-go 0.1.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 (121) hide show
  1. package/AGENTS.md +63 -0
  2. package/CONTRIBUTORS.md +75 -0
  3. package/LICENSE +21 -0
  4. package/Makefile +131 -0
  5. package/README.md +130 -0
  6. package/bin/cricinfo.js +44 -0
  7. package/cmd/cricinfo/main.go +15 -0
  8. package/go.mod +10 -0
  9. package/go.sum +10 -0
  10. package/internal/app/app.go +11 -0
  11. package/internal/app/app_test.go +122 -0
  12. package/internal/buildinfo/buildinfo.go +16 -0
  13. package/internal/cli/analysis.go +262 -0
  14. package/internal/cli/analysis_test.go +175 -0
  15. package/internal/cli/competitions.go +154 -0
  16. package/internal/cli/competitions_test.go +165 -0
  17. package/internal/cli/leagues.go +297 -0
  18. package/internal/cli/leagues_test.go +194 -0
  19. package/internal/cli/matches.go +403 -0
  20. package/internal/cli/matches_test.go +413 -0
  21. package/internal/cli/players.go +263 -0
  22. package/internal/cli/players_test.go +384 -0
  23. package/internal/cli/root.go +141 -0
  24. package/internal/cli/search.go +119 -0
  25. package/internal/cli/teams.go +214 -0
  26. package/internal/cli/teams_test.go +192 -0
  27. package/internal/cricinfo/analysis.go +1401 -0
  28. package/internal/cricinfo/analysis_phase15_test.go +267 -0
  29. package/internal/cricinfo/client.go +471 -0
  30. package/internal/cricinfo/client_test.go +280 -0
  31. package/internal/cricinfo/cmd/fixture-refresh/main.go +145 -0
  32. package/internal/cricinfo/competitions.go +405 -0
  33. package/internal/cricinfo/competitions_phase13_test.go +234 -0
  34. package/internal/cricinfo/coverage_ledger.go +122 -0
  35. package/internal/cricinfo/coverage_ledger_test.go +253 -0
  36. package/internal/cricinfo/decode.go +115 -0
  37. package/internal/cricinfo/decode_test.go +100 -0
  38. package/internal/cricinfo/entity_index.go +618 -0
  39. package/internal/cricinfo/entity_index_test.go +175 -0
  40. package/internal/cricinfo/fixture_matrix.go +243 -0
  41. package/internal/cricinfo/fixture_matrix_test.go +49 -0
  42. package/internal/cricinfo/fixtures_test.go +264 -0
  43. package/internal/cricinfo/historical_hydration.go +1641 -0
  44. package/internal/cricinfo/historical_phase14_test.go +542 -0
  45. package/internal/cricinfo/leagues.go +1210 -0
  46. package/internal/cricinfo/leagues_phase12_test.go +324 -0
  47. package/internal/cricinfo/live_leagues_test.go +169 -0
  48. package/internal/cricinfo/live_matches_test.go +203 -0
  49. package/internal/cricinfo/live_matrix_test.go +118 -0
  50. package/internal/cricinfo/live_players_test.go +122 -0
  51. package/internal/cricinfo/live_search_test.go +86 -0
  52. package/internal/cricinfo/live_smoke_test.go +213 -0
  53. package/internal/cricinfo/live_teams_test.go +104 -0
  54. package/internal/cricinfo/matches.go +1508 -0
  55. package/internal/cricinfo/matches_phase7_test.go +207 -0
  56. package/internal/cricinfo/matches_phase9_test.go +253 -0
  57. package/internal/cricinfo/normalize_entities.go +1727 -0
  58. package/internal/cricinfo/normalize_leagues.go +346 -0
  59. package/internal/cricinfo/players.go +1332 -0
  60. package/internal/cricinfo/players_phase10_test.go +174 -0
  61. package/internal/cricinfo/players_phase11_test.go +373 -0
  62. package/internal/cricinfo/render_contract.go +1088 -0
  63. package/internal/cricinfo/render_phase4_test.go +633 -0
  64. package/internal/cricinfo/renderer.go +1689 -0
  65. package/internal/cricinfo/resolver.go +813 -0
  66. package/internal/cricinfo/resolver_test.go +244 -0
  67. package/internal/cricinfo/teams.go +603 -0
  68. package/internal/cricinfo/teams_phase8_test.go +231 -0
  69. package/internal/cricinfo/testdata/fixtures/README.md +43 -0
  70. package/internal/cricinfo/testdata/fixtures/aux-competition-metadata/broadcasts.json +11 -0
  71. package/internal/cricinfo/testdata/fixtures/aux-competition-metadata/officials.json +150 -0
  72. package/internal/cricinfo/testdata/fixtures/details-plays/detail-110.json +157 -0
  73. package/internal/cricinfo/testdata/fixtures/details-plays/detail-52545007.json +145 -0
  74. package/internal/cricinfo/testdata/fixtures/details-plays/detail-52559021.json +143 -0
  75. package/internal/cricinfo/testdata/fixtures/details-plays/plays.json +15 -0
  76. package/internal/cricinfo/testdata/fixtures/endpoint-matrix.tsv +19 -0
  77. package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/fow-1.json +12 -0
  78. package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/fow.json +42 -0
  79. package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/innings-1-2.json +38 -0
  80. package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/partnership-1.json +31 -0
  81. package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/partnerships.json +42 -0
  82. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar-offdays.json +20 -0
  83. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar-ondays.json +21 -0
  84. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar.json +14 -0
  85. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-2025.json +13 -0
  86. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-group-1.json +13 -0
  87. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-groups.json +11 -0
  88. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-type-1.json +13 -0
  89. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-types.json +11 -0
  90. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/seasons.json +30 -0
  91. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings-item-1.json +72 -0
  92. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings-root.json +3 -0
  93. package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings.json +15 -0
  94. package/internal/cricinfo/testdata/fixtures/matches-competitions/competition.json +460 -0
  95. package/internal/cricinfo/testdata/fixtures/matches-competitions/event-1529474.json +86 -0
  96. package/internal/cricinfo/testdata/fixtures/matches-competitions/matchcards-1527966.json +368 -0
  97. package/internal/cricinfo/testdata/fixtures/matches-competitions/situation-1529474.json +10 -0
  98. package/internal/cricinfo/testdata/fixtures/players/athlete-1361257-statistics.json +126 -0
  99. package/internal/cricinfo/testdata/fixtures/players/athlete-1361257.json +113 -0
  100. package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores-1-1-statistics-0.json +208 -0
  101. package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores-1-2-statistics-0.json +252 -0
  102. package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores.json +74 -0
  103. package/internal/cricinfo/testdata/fixtures/players/roster-1361257-statistics-0.json +1008 -0
  104. package/internal/cricinfo/testdata/fixtures/root-discovery/events.json +72 -0
  105. package/internal/cricinfo/testdata/fixtures/root-discovery/root.json +28 -0
  106. package/internal/cricinfo/testdata/fixtures/team-competitor/competitor-789643.json +40 -0
  107. package/internal/cricinfo/testdata/fixtures/team-competitor/leaders-789643.json +353 -0
  108. package/internal/cricinfo/testdata/fixtures/team-competitor/records-789643.json +91 -0
  109. package/internal/cricinfo/testdata/fixtures/team-competitor/roster-1147772-object.json +231 -0
  110. package/internal/cricinfo/testdata/fixtures/team-competitor/roster-1147772.json +235 -0
  111. package/internal/cricinfo/testdata/fixtures/team-competitor/roster-789643.json +322 -0
  112. package/internal/cricinfo/testdata/fixtures/team-competitor/scores-789643.json +19 -0
  113. package/internal/cricinfo/testdata/fixtures/team-competitor/statistics-789643.json +629 -0
  114. package/internal/cricinfo/testdata/fixtures/team-competitor/team-789643-athletes.json +7 -0
  115. package/internal/cricinfo/testdata/fixtures/team-competitor/team-789643.json +67 -0
  116. package/internal/cricinfo/testdata/golden/match-empty.golden +1 -0
  117. package/internal/cricinfo/testdata/golden/match-list.golden +2 -0
  118. package/internal/cricinfo/testdata/golden/match-partial.golden +3 -0
  119. package/internal/cricinfo/types.go +54 -0
  120. package/package.json +51 -0
  121. package/scripts/postinstall.js +153 -0
package/AGENTS.md ADDED
@@ -0,0 +1,63 @@
1
+ # AGENTS.md
2
+
3
+ Guidance for coding agents working in `cricinfo-cli`.
4
+
5
+ ## Purpose
6
+
7
+ This repository ships the `cricinfo` Go CLI through npm. Treat the npm package, the Go binary, and the release workflow as one contract.
8
+
9
+ ## Architecture
10
+
11
+ - `cmd/cricinfo/main.go`: process entrypoint and exit handling.
12
+ - `internal/app/app.go`: command parsing and top-level dispatch.
13
+ - `internal/cli/`: command families, help text, and flag wiring.
14
+ - `internal/cricinfo/`: transport, normalization, rendering, and analysis logic.
15
+ - `bin/cricinfo.js`: npm shim that launches the installed native binary.
16
+ - `scripts/postinstall.js`: downloads the tagged binary or falls back to `go build`.
17
+ - `Makefile`: local build, test, smoke, and release helpers.
18
+ - `.github/workflows/release.yml`: tag-driven build and publish pipeline.
19
+
20
+ ## Local Commands
21
+
22
+ Prefer the checked-in `Makefile` targets:
23
+
24
+ - `make fmt`
25
+ - `make test`
26
+ - `make vet`
27
+ - `make lint`
28
+ - `make check`
29
+ - `make build`
30
+ - `make build-all`
31
+ - `make npm-smoke`
32
+ - `make acceptance`
33
+ - `make test-live`
34
+ - `make test-live-smoke`
35
+ - `make fixtures-refresh`
36
+ - `make install-local`
37
+
38
+ Direct commands that are also safe to use:
39
+
40
+ - `go test ./...`
41
+ - `go vet ./...`
42
+ - `npm run test`
43
+ - `npm run lint`
44
+
45
+ When running Node or npm commands through background helpers on this machine, prefer `zsh -lc '<command>'` so the login shell initializes the expected `PATH`.
46
+
47
+ ## Release Contract
48
+
49
+ Releases trigger on `v*` tags and expect:
50
+
51
+ - `NPM_TOKEN` to be configured in GitHub Actions.
52
+ - `package.json` to keep the published npm package name and `config.cliBinaryName` aligned with the CLI install contract.
53
+ - release assets to follow `<cli>_<goos>_<goarch>[.exe]`.
54
+ - `scripts/postinstall.js` to be able to fetch the matching GitHub release asset or build from source.
55
+
56
+ If you touch release artifacts or the binary name, update `package.json`, `bin/cricinfo.js`, `scripts/postinstall.js`, `Makefile`, and `.github/workflows/release.yml` in the same change.
57
+
58
+ ## Guardrails
59
+
60
+ - Prefer additive changes and keep the existing CLI naming contract intact.
61
+ - Do not rewrite user changes in unrelated files.
62
+ - Keep help output concrete and command-local so `<command> --help` explains the next step.
63
+ - If you add dependencies, commit the updated `go.sum` and verify the release workflow still builds cleanly.
@@ -0,0 +1,75 @@
1
+ # CONTRIBUTORS.md
2
+
3
+ Maintainer notes for this template repository.
4
+
5
+ ## Prerequisites
6
+
7
+ - Go `1.26+`
8
+ - Node `18+`
9
+ - npm account with publish rights for the package name in `package.json`
10
+ - GitHub repo admin access
11
+
12
+ ## Local development
13
+
14
+ ```bash
15
+ make check
16
+ make build
17
+ ./dist/cricinfo --help
18
+ ```
19
+
20
+ Install command locally:
21
+
22
+ ```bash
23
+ make install-local
24
+ cricinfo --help
25
+ ```
26
+
27
+ ## Release process
28
+
29
+ 1. Ensure `main` is green:
30
+
31
+ ```bash
32
+ make check
33
+ ```
34
+
35
+ 2. Prepare release tag:
36
+
37
+ ```bash
38
+ make release-tag VERSION=0.1.0
39
+ ```
40
+
41
+ 3. GitHub Actions `release` workflow runs automatically:
42
+ - quality checks
43
+ - cross-platform binary build
44
+ - GitHub release publish
45
+ - npm publish
46
+
47
+ ## Required GitHub secret
48
+
49
+ - `NPM_TOKEN`: npm automation token with publish rights for your package.
50
+
51
+ Set via GitHub CLI:
52
+
53
+ ```bash
54
+ gh secret set NPM_TOKEN --repo amxv/cricinfo-cli
55
+ ```
56
+
57
+ ## npm token setup
58
+
59
+ Create token at npm:
60
+
61
+ - Profile -> Access Tokens -> Create New Token
62
+ - Use an automation/granular token scoped to required package/org
63
+
64
+ Validate auth locally:
65
+
66
+ ```bash
67
+ npm whoami
68
+ ```
69
+
70
+ ## Notes on package naming
71
+
72
+ Before first publish, set a package name you control in `package.json`.
73
+
74
+ - Example unscoped: `"name": "your-cli-name"`
75
+ - Example scoped: `"name": "@your-scope/your-cli-name"`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 amxv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/Makefile ADDED
@@ -0,0 +1,131 @@
1
+ SHELL := /bin/bash
2
+ NODE_SHELL ?= /bin/zsh -lc
3
+
4
+ GO ?= go
5
+ GOFMT ?= gofmt
6
+ BIN_NAME ?= cricinfo
7
+ CMD_PATH ?= ./cmd/$(BIN_NAME)
8
+ DIST_DIR ?= dist
9
+ BIN_PATH ?= $(DIST_DIR)/$(BIN_NAME)
10
+ VERSION ?= $(shell node -p "require('./package.json').version" 2>/dev/null)
11
+ LDFLAGS ?= -s -w -X github.com/amxv/cricinfo-cli/internal/buildinfo.Version=$(if $(VERSION),$(VERSION),dev)
12
+ ACCEPTANCE_LEAGUE ?= 11132
13
+ ACCEPTANCE_MATCH ?= 1527689
14
+ ACCEPTANCE_PLAYER ?= Virat Kohli
15
+ ACCEPTANCE_TEAM ?= rr
16
+
17
+ .PHONY: help fmt test test-live test-live-smoke fixtures-refresh vet lint check build build-all npm-smoke acceptance install-local clean release-tag
18
+
19
+ help:
20
+ @echo "cricinfo command runner"
21
+ @echo ""
22
+ @echo "Targets:"
23
+ @echo " make fmt - format Go files"
24
+ @echo " make test - run go test ./..."
25
+ @echo " make test-live - run opt-in live Cricinfo matrix tests"
26
+ @echo " make test-live-smoke - run opt-in live smoke coverage tests"
27
+ @echo " make fixtures-refresh - refresh curated live fixtures into testdata"
28
+ @echo " make vet - run go vet ./..."
29
+ @echo " make lint - run Node script checks"
30
+ @echo " make check - fmt + test + vet + lint"
31
+ @echo " make build - build local binary to dist/cricinfo"
32
+ @echo " make build-all - build release binaries for 5 target platforms"
33
+ @echo " make npm-smoke - pack + install npm tarball in a temp prefix and run cricinfo --help"
34
+ @echo " make acceptance - run live end-to-end CLI acceptance checks over key command families"
35
+ @echo " make install-local- install CLI to ~/.local/bin/cricinfo"
36
+ @echo " make clean - remove dist artifacts"
37
+ @echo " make release-tag - create and push git tag (requires VERSION=x.y.z)"
38
+
39
+ fmt:
40
+ @$(GOFMT) -w $$(find . -type f -name '*.go' -not -path './dist/*')
41
+
42
+ test:
43
+ @$(GO) test ./...
44
+
45
+ test-live:
46
+ @CRICINFO_LIVE_MATRIX=1 $(GO) test ./internal/cricinfo -run 'TestLive' -count=1
47
+
48
+ test-live-smoke:
49
+ @CRICINFO_LIVE_SMOKE=1 $(GO) test ./internal/cricinfo -run 'TestLiveSmoke' -count=1
50
+
51
+ fixtures-refresh:
52
+ @$(GO) run ./internal/cricinfo/cmd/fixture-refresh --write
53
+
54
+ vet:
55
+ @$(GO) vet ./...
56
+
57
+ lint:
58
+ @$(NODE_SHELL) 'npm run lint'
59
+
60
+ check: fmt test vet lint
61
+
62
+ build:
63
+ @mkdir -p $(DIST_DIR)
64
+ @$(GO) build -trimpath -ldflags="$(LDFLAGS)" -o $(BIN_PATH) $(CMD_PATH)
65
+
66
+ build-all:
67
+ @mkdir -p $(DIST_DIR)
68
+ @for target in "darwin amd64" "darwin arm64" "linux amd64" "linux arm64" "windows amd64"; do \
69
+ set -- $$target; \
70
+ GOOS=$$1; GOARCH=$$2; \
71
+ EXT=""; \
72
+ if [ "$$GOOS" = "windows" ]; then EXT=".exe"; fi; \
73
+ echo "Building $(BIN_NAME) for $$GOOS/$$GOARCH"; \
74
+ CGO_ENABLED=0 GOOS=$$GOOS GOARCH=$$GOARCH $(GO) build -trimpath -ldflags="$(LDFLAGS)" -o "$(DIST_DIR)/$(BIN_NAME)_$$GOOS_$$GOARCH$$EXT" $(CMD_PATH); \
75
+ done
76
+
77
+ npm-smoke:
78
+ @set -euo pipefail; \
79
+ PACK_NAME="$$( $(NODE_SHELL) "npm pack --silent" )"; \
80
+ TMP_DIR="tmp/npm-smoke.$$"; \
81
+ /bin/rm -rf "$$TMP_DIR"; \
82
+ mkdir -p "$$TMP_DIR"; \
83
+ trap '/bin/rm -rf "$$TMP_DIR" "$$PACK_NAME"' EXIT; \
84
+ $(NODE_SHELL) "npm install --prefix '$$TMP_DIR/prefix' './$$PACK_NAME' >/dev/null"; \
85
+ $(NODE_SHELL) "'$$TMP_DIR/prefix/node_modules/.bin/$(BIN_NAME)' --help >/dev/null"; \
86
+ echo "npm smoke ok: $$PACK_NAME"
87
+
88
+ acceptance: build
89
+ @set -euo pipefail; \
90
+ $(MAKE) npm-smoke; \
91
+ BIN="$(BIN_PATH)"; \
92
+ "$$BIN" --help >/dev/null; \
93
+ "$$BIN" matches --help >/dev/null; \
94
+ "$$BIN" players --help >/dev/null; \
95
+ "$$BIN" teams --help >/dev/null; \
96
+ "$$BIN" leagues --help >/dev/null; \
97
+ "$$BIN" analysis --help >/dev/null; \
98
+ "$$BIN" matches list --limit 5 --format json >/dev/null; \
99
+ "$$BIN" matches live --limit 5 --format json >/dev/null; \
100
+ "$$BIN" matches show "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
101
+ "$$BIN" matches scorecard "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
102
+ "$$BIN" matches innings "$(ACCEPTANCE_MATCH)" --team "$(ACCEPTANCE_TEAM)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
103
+ "$$BIN" players search "$(ACCEPTANCE_PLAYER)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
104
+ "$$BIN" players profile "$(ACCEPTANCE_PLAYER)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
105
+ "$$BIN" players match-stats "$(ACCEPTANCE_PLAYER)" --match "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
106
+ "$$BIN" players deliveries "$(ACCEPTANCE_PLAYER)" --match "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
107
+ "$$BIN" teams show "$(ACCEPTANCE_TEAM)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
108
+ "$$BIN" teams roster "$(ACCEPTANCE_TEAM)" --match "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
109
+ "$$BIN" teams leaders "$(ACCEPTANCE_TEAM)" --match "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
110
+ "$$BIN" leagues show "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
111
+ "$$BIN" leagues seasons "$(ACCEPTANCE_LEAGUE)" --format json >/dev/null; \
112
+ "$$BIN" seasons show "$(ACCEPTANCE_LEAGUE)" --season 2025 --format json >/dev/null; \
113
+ "$$BIN" analysis bowling --metric economy --scope "match:$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --top 10 --format json >/dev/null; \
114
+ "$$BIN" analysis dismissals --league "$(ACCEPTANCE_LEAGUE)" --seasons 2025 --top 5 --format json >/dev/null; \
115
+ "$$BIN" analysis partnerships --scope "match:$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --top 5 --format json >/dev/null; \
116
+ ! "$$BIN" analysis bowling --metric economy --scope "match:$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --top 10 --format text | grep -E '(https?://|/v2/sports/cricket)'; \
117
+ ! "$$BIN" teams leaders "$(ACCEPTANCE_TEAM)" --match "$(ACCEPTANCE_MATCH)" --league "$(ACCEPTANCE_LEAGUE)" --format text | grep -E '(https?://|/v2/sports/cricket)'; \
118
+ echo "acceptance ok: live command traversal and json rendering"
119
+
120
+ install-local: build
121
+ @mkdir -p $$HOME/.local/bin
122
+ @install -m 755 $(BIN_PATH) $$HOME/.local/bin/$(BIN_NAME)
123
+ @echo "Installed $(BIN_NAME) to $$HOME/.local/bin/$(BIN_NAME)"
124
+
125
+ clean:
126
+ @rm -rf $(DIST_DIR)
127
+
128
+ release-tag:
129
+ @test -n "$(VERSION)" || (echo "Usage: make release-tag VERSION=x.y.z" && exit 1)
130
+ @git tag "v$(VERSION)"
131
+ @git push origin "v$(VERSION)"
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # cricinfo
2
+
3
+ `cricinfo` is a Go-powered Cricinfo CLI published on npm as `cricinfo-cli-go`. It is designed for both human workflows and agent workflows, with readable text output by default and structured JSON or JSONL for automation.
4
+
5
+ ## Install
6
+
7
+ Install the latest published package globally:
8
+
9
+ ```bash
10
+ npm i -g cricinfo-cli-go
11
+ cricinfo --version
12
+ cricinfo --help
13
+ ```
14
+
15
+ If you are working from source, the repo also ships local build targets:
16
+
17
+ ```bash
18
+ make build
19
+ make install-local
20
+ ```
21
+
22
+ The npm package installs a platform-specific binary when available and falls back to a local Go build during `postinstall` if needed.
23
+
24
+ ## Usage
25
+
26
+ Start at the root help, then drill into the family you need:
27
+
28
+ ```bash
29
+ cricinfo --help
30
+ cricinfo matches --help
31
+ cricinfo players --help
32
+ cricinfo teams --help
33
+ cricinfo leagues --help
34
+ cricinfo analysis --help
35
+ ```
36
+
37
+ Common command families include:
38
+
39
+ ```text
40
+ matches
41
+ players
42
+ teams
43
+ leagues
44
+ seasons
45
+ standings
46
+ competitions
47
+ search
48
+ analysis
49
+ ```
50
+
51
+ Typical workflows:
52
+
53
+ ```bash
54
+ # Discover current or recent match data
55
+ cricinfo matches list
56
+ cricinfo matches live
57
+ cricinfo matches show 1529474
58
+ cricinfo matches scorecard 1529474
59
+
60
+ # Explore players and teams
61
+ cricinfo players profile 1361257
62
+ cricinfo players match-stats 1361257 --match 1529474
63
+ cricinfo teams roster 789643 --match 1529474
64
+
65
+ # Traverse leagues and seasons
66
+ cricinfo leagues show 19138
67
+ cricinfo leagues seasons 19138
68
+ cricinfo seasons show 19138 --season 2025
69
+
70
+ # Derived analysis
71
+ cricinfo analysis dismissals --league 19138 --seasons 2025
72
+ cricinfo analysis bowling --metric economy --scope match:1529474
73
+ cricinfo analysis batting --metric strike-rate --scope season:2025 --league 19138
74
+ cricinfo analysis partnerships --scope season:2025 --league 19138
75
+ ```
76
+
77
+ ## Output Modes
78
+
79
+ Use `--format text|json|jsonl` to match the consumer:
80
+
81
+ ```bash
82
+ cricinfo matches show 1529474 --format json
83
+ cricinfo matches list --format jsonl
84
+ cricinfo players profile 1361257 --format json
85
+ ```
86
+
87
+ Helpful global flags:
88
+
89
+ - `--verbose` for richer summaries
90
+ - `--all-fields` to retain extended entity data in structured output
91
+ - `--format jsonl` for list-oriented machine processing
92
+
93
+ ## Development
94
+
95
+ Use the checked-in `Makefile` targets whenever possible:
96
+
97
+ ```bash
98
+ make fmt
99
+ make test
100
+ make vet
101
+ make lint
102
+ make check
103
+ make build
104
+ make build-all
105
+ make npm-smoke
106
+ make acceptance
107
+ make test-live
108
+ make test-live-smoke
109
+ make fixtures-refresh
110
+ ```
111
+
112
+ `make check` runs format, tests, vet, and lint. `make acceptance` performs a live end-to-end traversal across install/help, matches, players, teams, leagues, analysis, and JSON rendering.
113
+
114
+ ## Release
115
+
116
+ Releases are tag-driven. Push a `vX.Y.Z` tag and GitHub Actions will:
117
+
118
+ 1. run Go and Node quality checks
119
+ 2. build release binaries for the supported platforms
120
+ 3. publish the GitHub release assets
121
+ 4. publish the npm package at the tag version
122
+
123
+ Release artifact conventions:
124
+
125
+ - binary name: `cricinfo`
126
+ - GitHub release assets: `cricinfo_<goos>_<goarch>[.exe]`
127
+ - npm shim: `bin/cricinfo.js`
128
+ - install fallback: `scripts/postinstall.js`
129
+
130
+ If you change the CLI name or release artifact layout, update `package.json`, `bin/cricinfo.js`, `scripts/postinstall.js`, `Makefile`, and `.github/workflows/release.yml` together.
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+ const { spawnSync } = require("node:child_process");
6
+
7
+ const pkg = require("../package.json");
8
+ const cliName = resolveCLIName(pkg);
9
+ const executableName = process.platform === "win32" ? `${cliName}.exe` : `${cliName}-bin`;
10
+ const executablePath = path.join(__dirname, executableName);
11
+
12
+ if (!fs.existsSync(executablePath)) {
13
+ console.error(`${cliName} binary is not installed. Re-run: npm rebuild -g ${pkg.name}`);
14
+ process.exit(1);
15
+ }
16
+
17
+ const child = spawnSync(executablePath, process.argv.slice(2), { stdio: "inherit" });
18
+
19
+ if (child.error) {
20
+ console.error(child.error.message);
21
+ process.exit(1);
22
+ }
23
+
24
+ if (child.signal) {
25
+ process.kill(process.pid, child.signal);
26
+ }
27
+
28
+ process.exit(child.status ?? 1);
29
+
30
+ function resolveCLIName(packageJSON) {
31
+ const configured = `${packageJSON?.config?.cliBinaryName || ""}`.trim();
32
+ if (configured) {
33
+ return configured;
34
+ }
35
+
36
+ if (packageJSON?.bin && typeof packageJSON.bin === "object") {
37
+ const names = Object.keys(packageJSON.bin);
38
+ if (names.length > 0 && `${names[0]}`.trim()) {
39
+ return `${names[0]}`.trim();
40
+ }
41
+ }
42
+
43
+ return "cricinfo";
44
+ }
@@ -0,0 +1,15 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "os"
6
+
7
+ "github.com/amxv/cricinfo-cli/internal/app"
8
+ )
9
+
10
+ func main() {
11
+ if err := app.Run(os.Args[1:], os.Stdout, os.Stderr); err != nil {
12
+ fmt.Fprintln(os.Stderr, "Error:", err)
13
+ os.Exit(1)
14
+ }
15
+ }
package/go.mod ADDED
@@ -0,0 +1,10 @@
1
+ module github.com/amxv/cricinfo-cli
2
+
3
+ go 1.26
4
+
5
+ require github.com/spf13/cobra v1.8.1
6
+
7
+ require (
8
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
9
+ github.com/spf13/pflag v1.0.5 // indirect
10
+ )
package/go.sum ADDED
@@ -0,0 +1,10 @@
1
+ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
2
+ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
3
+ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
4
+ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
5
+ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
6
+ github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
7
+ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
8
+ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
9
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -0,0 +1,11 @@
1
+ package app
2
+
3
+ import (
4
+ "io"
5
+
6
+ "github.com/amxv/cricinfo-cli/internal/cli"
7
+ )
8
+
9
+ func Run(args []string, stdout, stderr io.Writer) error {
10
+ return cli.Run(args, stdout, stderr)
11
+ }
@@ -0,0 +1,122 @@
1
+ package app
2
+
3
+ import (
4
+ "bytes"
5
+ "strings"
6
+ "testing"
7
+ )
8
+
9
+ func TestRunRootHelp(t *testing.T) {
10
+ var out bytes.Buffer
11
+ var errBuf bytes.Buffer
12
+
13
+ err := Run([]string{"--help"}, &out, &errBuf)
14
+ if err != nil {
15
+ t.Fatalf("Run returned error: %v", err)
16
+ }
17
+
18
+ help := out.String()
19
+ if !strings.Contains(help, "Usage:") {
20
+ t.Fatalf("expected help output, got: %q", out.String())
21
+ }
22
+ if !strings.Contains(help, "--version") {
23
+ t.Fatalf("expected --version in help output, got: %q", out.String())
24
+ }
25
+ if !strings.Contains(help, "matches") || !strings.Contains(help, "players") {
26
+ t.Fatalf("expected placeholder groups in root help, got: %q", help)
27
+ }
28
+ }
29
+
30
+ func TestRunVersion(t *testing.T) {
31
+ var out bytes.Buffer
32
+ var errBuf bytes.Buffer
33
+
34
+ err := Run([]string{"--version"}, &out, &errBuf)
35
+ if err != nil {
36
+ t.Fatalf("Run returned error: %v", err)
37
+ }
38
+
39
+ if !strings.Contains(out.String(), "cricinfo ") {
40
+ t.Fatalf("unexpected version output: %q", out.String())
41
+ }
42
+ }
43
+
44
+ func TestRunMatchesGroupHelp(t *testing.T) {
45
+ var out bytes.Buffer
46
+ var errBuf bytes.Buffer
47
+
48
+ err := Run([]string{"matches", "--help"}, &out, &errBuf)
49
+ if err != nil {
50
+ t.Fatalf("Run returned error: %v", err)
51
+ }
52
+
53
+ help := out.String()
54
+ if !strings.Contains(help, "Next steps:") {
55
+ t.Fatalf("expected next-step guidance in help output, got: %q", help)
56
+ }
57
+ if !strings.Contains(help, "cricinfo matches live") || !strings.Contains(help, "cricinfo matches show <match>") {
58
+ t.Fatalf("expected matches drill-down commands in help output, got: %q", help)
59
+ }
60
+ }
61
+
62
+ func TestRunUnknownCommand(t *testing.T) {
63
+ var out bytes.Buffer
64
+ var errBuf bytes.Buffer
65
+
66
+ err := Run([]string{"unknown"}, &out, &errBuf)
67
+ if err == nil {
68
+ t.Fatal("expected error for unknown command")
69
+ }
70
+ if !strings.Contains(err.Error(), `unknown command "unknown"`) {
71
+ t.Fatalf("expected unknown command error, got: %v", err)
72
+ }
73
+ if !strings.Contains(err.Error(), "run `cricinfo --help`") {
74
+ t.Fatalf("expected unknown command help hint, got: %v", err)
75
+ }
76
+ }
77
+
78
+ func TestRunGlobalFlagsPropagateToSubcommands(t *testing.T) {
79
+ var out bytes.Buffer
80
+ var errBuf bytes.Buffer
81
+
82
+ err := Run([]string{"players", "--format", "json", "--verbose", "--all-fields", "--help"}, &out, &errBuf)
83
+ if err != nil {
84
+ t.Fatalf("Run returned error: %v", err)
85
+ }
86
+
87
+ help := out.String()
88
+ if !strings.Contains(help, "--format") || !strings.Contains(help, "--verbose") || !strings.Contains(help, "--all-fields") {
89
+ t.Fatalf("expected global flags in subcommand help output, got: %q", help)
90
+ }
91
+ }
92
+
93
+ func TestRunRejectsUnknownFormat(t *testing.T) {
94
+ var out bytes.Buffer
95
+ var errBuf bytes.Buffer
96
+
97
+ err := Run([]string{"players", "--format", "yaml"}, &out, &errBuf)
98
+ if err == nil {
99
+ t.Fatal("expected error for invalid --format value")
100
+ }
101
+ if !strings.Contains(err.Error(), `invalid value "yaml" for --format`) {
102
+ t.Fatalf("unexpected invalid format error: %v", err)
103
+ }
104
+ }
105
+
106
+ func TestRunSearchGroupHelp(t *testing.T) {
107
+ var out bytes.Buffer
108
+ var errBuf bytes.Buffer
109
+
110
+ err := Run([]string{"search", "--help"}, &out, &errBuf)
111
+ if err != nil {
112
+ t.Fatalf("Run returned error: %v", err)
113
+ }
114
+
115
+ help := out.String()
116
+ if !strings.Contains(help, "players") || !strings.Contains(help, "teams") || !strings.Contains(help, "leagues") || !strings.Contains(help, "matches") {
117
+ t.Fatalf("expected entity search subcommands in help output, got: %q", help)
118
+ }
119
+ if !strings.Contains(help, "--league") || !strings.Contains(help, "--match") {
120
+ t.Fatalf("expected search context flags in help output, got: %q", help)
121
+ }
122
+ }
@@ -0,0 +1,16 @@
1
+ package buildinfo
2
+
3
+ import "strings"
4
+
5
+ const defaultVersion = "dev"
6
+
7
+ // Version is overridden at build time via linker flags.
8
+ var Version = defaultVersion
9
+
10
+ func CurrentVersion() string {
11
+ trimmed := strings.TrimSpace(Version)
12
+ if trimmed == "" {
13
+ return defaultVersion
14
+ }
15
+ return trimmed
16
+ }