@nekosuneprojects/gaming-infos 2.1.0 → 2.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.
@@ -0,0 +1,72 @@
1
+ name: Sync APINODE fallback caches
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ # Daily at 03:23 UTC. GitHub Actions cron uses UTC.
7
+ - cron: "23 3 * * *"
8
+ push:
9
+ branches:
10
+ - main
11
+ paths:
12
+ - "scripts/sync-api-cache.js"
13
+ - "scripts/sync-gaming-info-cache.js"
14
+ - "scripts/sync-game-code-cache.js"
15
+ - "scripts/sync-all-cache.js"
16
+ - "scripts/cache-sync-smoke.js"
17
+ - "scripts/game-code-cache-smoke.js"
18
+ - "gamecodes.js"
19
+ - "index.js"
20
+ - "package.json"
21
+ - "CACHE_SYNC.md"
22
+ - ".github/workflows/sync-api-cache.yml"
23
+
24
+ permissions:
25
+ contents: write
26
+
27
+ concurrency:
28
+ group: gaming-infos-api-cache
29
+ cancel-in-progress: false
30
+
31
+ jobs:
32
+ sync:
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - name: Checkout
36
+ uses: actions/checkout@v4
37
+ with:
38
+ fetch-depth: 0
39
+
40
+ - name: Use Node.js 22
41
+ uses: actions/setup-node@v4
42
+ with:
43
+ node-version: 22
44
+
45
+ - name: Test atomic cache behavior
46
+ run: npm run test:all-cache
47
+
48
+ - name: Mirror APINODE gaming-infos and game codes
49
+ run: npm run sync:cache
50
+ env:
51
+ GAMING_INFOS_API_BASE: https://api.nekosunevr.co.uk
52
+ GAMING_INFOS_API_PATH: /v5/games/api/gaming-infos
53
+ GAME_CODES_API_PATH: /v5/games/api/codes
54
+ GAMING_INFOS_CACHE_TIMEOUT_MS: 20000
55
+ GAMING_INFOS_CACHE_RETRIES: 2
56
+ GAME_CODES_CACHE_TIMEOUT_MS: 20000
57
+ GAME_CODES_CACHE_RETRIES: 2
58
+ GAME_CODES_CACHE_GAME_DELAY_MS: 150
59
+
60
+ - name: Commit fallback changes
61
+ shell: bash
62
+ run: |
63
+ git add -A data
64
+ if git diff --cached --quiet; then
65
+ echo "Fallback caches already match APINODE."
66
+ exit 0
67
+ fi
68
+
69
+ git config user.name "github-actions[bot]"
70
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
71
+ git commit -m "chore(cache): mirror APINODE fallback data [skip ci]"
72
+ git push
package/CACHE_SYNC.md ADDED
@@ -0,0 +1,172 @@
1
+ # APINODE fallback-cache mirror
2
+
3
+ `@nekosuneprojects/gaming-infos` is API-first. Normal reads try the NekoSuneVR V5 API before using bundled JSON under `data/`.
4
+
5
+ The repository keeps **two independent last-good fallback snapshots** synchronized automatically:
6
+
7
+ - Gaming Infos: `GET /v5/games/api/gaming-infos`
8
+ - Game Codes: `GET /v5/games/api/codes`
9
+
10
+ ## Schedule
11
+
12
+ The GitHub Action runs **once every day at 03:23 UTC** and can also be started manually with `workflow_dispatch`.
13
+
14
+ It also runs when the cache implementation itself changes so a newly deployed cache format can be populated immediately.
15
+
16
+ ## Mirrored gaming-infos datasets
17
+
18
+ | Game | API type(s) |
19
+ |---|---|
20
+ | VRChat | `players`, `groups`, `worlds`, `avatars` |
21
+ | Genshin Impact | `characters` |
22
+ | Honkai: Star Rail | `characters` |
23
+ | Neverness to Everness | `characters` |
24
+ | Wuthering Waves | `characters` (Resonators) |
25
+ | Warframe | `characters` (Warframes) |
26
+ | Fortnite | `characters` (current/released Battle Royale characters) |
27
+ | Zenless Zone Zero | `characters` (Agents) |
28
+ | Tower of Fantasy | `characters` (Simulacra) |
29
+ | Arknights: Endfield | `characters` (Operators) |
30
+
31
+ ## Mirrored Game Codes endpoints
32
+
33
+ The daily mirror also caches:
34
+
35
+ ```text
36
+ GET /v5/games/api/codes
37
+ GET /v5/games/api/codes/status
38
+ GET /v5/games/api/codes/:game?includeUnknown=true
39
+ ```
40
+
41
+ `/codes/status` only reads APINODE's cached source state. It does **not** trigger source website refreshes.
42
+
43
+ The per-game request uses `includeUnknown=true`, so the fallback contains all three buckets when available:
44
+
45
+ ```json
46
+ {
47
+ "Active": [],
48
+ "Expired": [],
49
+ "Unknown": []
50
+ }
51
+ ```
52
+
53
+ The mirror does not call every `/:game/:code` endpoint. `GameCode(game, code)` can search the full cached per-game snapshot during an outage, which keeps the daily request count low.
54
+
55
+ Game-code fallback layout:
56
+
57
+ ```text
58
+ data/game-codes/
59
+ ├── directory.json
60
+ ├── status.json
61
+ ├── .cache-manifest.json
62
+ └── games/
63
+ ├── fortnite.json
64
+ ├── warframe.json
65
+ ├── genshin-impact.json
66
+ └── ...
67
+ ```
68
+
69
+ ## Atomic synchronization / deletion behavior
70
+
71
+ Each cache is authoritative only **after its complete API download succeeds**.
72
+
73
+ For Gaming Infos:
74
+
75
+ 1. Temporarily preserve `data/game-codes/` outside the gaming-info snapshot.
76
+ 2. Fetch the root gaming-infos endpoint.
77
+ 3. Fetch every configured game's meta endpoint.
78
+ 4. Fetch every configured type-list endpoint.
79
+ 5. Validate every response and entry slug.
80
+ 6. Build a completely separate temporary snapshot.
81
+ 7. Atomically replace the gaming-info `data/` snapshot.
82
+ 8. Restore the previous game-code fallback before the code phase begins.
83
+
84
+ For Game Codes:
85
+
86
+ 1. Fetch `/codes` and validate its game directory.
87
+ 2. Fetch cache-only `/codes/status`.
88
+ 3. Fetch every listed game's full `Active` / `Expired` / `Unknown` snapshot.
89
+ 4. Build a separate temporary `data/game-codes/` tree.
90
+ 5. Only after every game succeeds, atomically replace the old game-code snapshot.
91
+
92
+ Because successful API snapshots are authoritative, **adds, changes and removals are mirrored**. If APINODE removes an entry/code/game, the corresponding fallback disappears on the next successful daily sync.
93
+
94
+ If APINODE is down, times out, returns 429/5xx, or one required endpoint fails halfway through, that cache is **not replaced**. The previous last-good fallback remains available.
95
+
96
+ ## Package API
97
+
98
+ Gaming Infos functions remain available:
99
+
100
+ ```js
101
+ const info = require('@nekosuneprojects/gaming-infos');
102
+
103
+ await info.Games();
104
+ await info.List('vrchat', 'avatars');
105
+ await info.Characters('wutheringwaves', 'cartethyia');
106
+ ```
107
+
108
+ Game Codes helpers use live APINODE first and the daily fallback second:
109
+
110
+ ```js
111
+ await info.Codes(); // GET /v5/games/api/codes
112
+ await info.CodesStatus(); // GET /v5/games/api/codes/status
113
+ await info.GameCodes('fortnite'); // Active + Expired
114
+ await info.GameCodes('fortnite', { includeUnknown: true });
115
+ await info.GameCode('fortnite', 'NEKOSUNEVR');
116
+ await info.CodeCacheInfo();
117
+ ```
118
+
119
+ Per-game fallback filtering is supported for `category` and `claimType` as well.
120
+
121
+ ## Commands
122
+
123
+ ```bash
124
+ # Test both atomic cache systems
125
+ npm run test:all-cache
126
+
127
+ # Mirror both Gaming Infos and Game Codes
128
+ npm run sync:cache
129
+
130
+ # Debug individually
131
+ npm run sync:gaming-infos-cache
132
+ npm run sync:game-codes-cache
133
+ npm run test:cache-sync
134
+ npm run test:game-code-cache
135
+ ```
136
+
137
+ Override APINODE while testing:
138
+
139
+ ```bash
140
+ GAMING_INFOS_API_BASE=http://localhost:3000 npm run sync:cache
141
+ ```
142
+
143
+ Useful variables:
144
+
145
+ | Variable | Default | Purpose |
146
+ |---|---|---|
147
+ | `GAMING_INFOS_API_BASE` | `https://api.nekosunevr.co.uk` | APINODE host used by both caches |
148
+ | `GAMING_INFOS_API_PATH` | `/v5/games/api/gaming-infos` | Gaming Infos path |
149
+ | `GAME_CODES_API_PATH` | `/v5/games/api/codes` | Game Codes path |
150
+ | `GAMING_INFOS_CACHE_TIMEOUT_MS` | `15000` | Gaming Infos per-request timeout |
151
+ | `GAMING_INFOS_CACHE_RETRIES` | `2` | Gaming Infos retry count |
152
+ | `GAME_CODES_CACHE_TIMEOUT_MS` | `15000` | Game Codes per-request timeout |
153
+ | `GAME_CODES_CACHE_RETRIES` | `2` | Game Codes retry count |
154
+ | `GAME_CODES_CACHE_GAME_DELAY_MS` | `150` | Small delay between game-list requests |
155
+
156
+ ## Runtime fallback behavior
157
+
158
+ The package does **not** use the cache instead of live data. It remains API-first:
159
+
160
+ ```text
161
+ application
162
+ ↓
163
+ live APINODE
164
+ ├─ success → current API response
165
+ └─ unavailable/error → last-good bundled fallback
166
+ ```
167
+
168
+ A successful changed Gaming Infos snapshot records `data/.cache-manifest.json`. Game Codes records its own `data/game-codes/.cache-manifest.json`. Both include source URL, content hash, counts, synchronization time and add/change/remove statistics.
169
+
170
+ The hash comparison ignores manifest timestamps, so an unchanged API dataset does not create a pointless daily commit.
171
+
172
+ Note: npm releases are immutable. Repository fallback files update daily, but an already-installed npm version keeps the bundled snapshot from that package release until upgraded. Live API reads still remain current whenever APINODE is available.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 2.2.0 - 2026-08-24
11
+
12
+ ### Added
13
+ - Added API-first Game Codes helpers: `Codes()`, `CodesStatus()`, `GameCodes(game, options)`, `GameCode(game, code, options)`, and `CodeCacheInfo()`.
14
+ - Added an atomic `data/game-codes/` fallback mirror for `/v5/games/api/codes`, cache-only `/status`, and every per-game Active/Expired/Unknown dataset.
15
+ - Added game-code fallback alias resolution using the cached `/codes` directory aliases.
16
+ - Added game-code cache smoke tests covering additions, changes, removals, and partial API outages.
17
+ - Added `Avatars(game, name)` for VRChat avatar records.
18
+ - Added public Gaming Infos support for Wuthering Waves Resonators, Warframe Warframes, Fortnite current/released Battle Royale characters, Zenless Zone Zero Agents, Tower of Fantasy Simulacra, and Arknights: Endfield Operators.
19
+ - Expanded the mirrored VRChat datasets to include players, groups, worlds, and avatars.
20
+ - Added `CacheInfo()` for inspecting the last mirrored Gaming Infos snapshot.
21
+ - Added automatic fallback-cache manifests with source URL, content hash, counts, and add/change/remove statistics.
22
+
23
+ ### Changed
24
+ - `npm run sync:cache` now mirrors both Gaming Infos and Game Codes.
25
+ - The automatic cache workflow now runs once daily at 03:23 UTC instead of every six hours.
26
+ - Gaming Infos and Game Codes are mirrored as independent atomic snapshots so a failure in one cache cannot destroy the other cache's last-good data.
27
+ - Successful mirror runs now synchronize additions, updates, and removals from APINODE while failed or partial runs preserve the previous fallback snapshot.
28
+ - Local fallback entities expose stable slugs so offline lookups match live API behavior more closely.
29
+ - Expanded the package description and keywords for the new games, VRChat avatars, and redeem/creator-code support.
30
+ - Reworked `README.md` to document the full supported-game matrix, API-first fallback behavior, Game Codes API helpers, daily sync workflow, cache commands, configuration, and examples.
31
+
10
32
  ## 2.1.0 - 2026-08-02
11
33
 
12
34
  ### Added
@@ -27,10 +49,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
27
49
  - Renamed package from `vrchat-infos` to `gaming-infos` to reflect multi-game support (VRChat today, Genshin Impact and more coming soon).
28
50
  - `data/` is now scoped per game: `data/<game>/worlds`, `data/<game>/groups`, `data/<game>/players`, `data/<game>/meta.json`. VRChat data moved under `data/vrchat/`.
29
51
  - Every lookup function now takes a `game` as its first argument, e.g. `Worlds('vrchat', 'theblackcat')` instead of `Worlds('theblackcat')`.
30
- - Added `Game(game)` for game-level meta info, `Characters(game, name)` for character-based games, and a generic `Get(game, type, name)` escape hatch.
52
+ - Added `Game(game)` for game-level info, `Characters(game, name)` for character-based games, and a generic `Get(game, type, name)` escape hatch.
31
53
 
32
54
  ### Added
33
55
  - Lookups now try the NekoSuneVR V5 API first (`GAMING_INFOS_API_BASE`, default `https://api.nekosunevr.co.uk`) and fall back to the bundled local JSON if the API is unreachable, so data can be updated in real time without republishing this package. Set `GAMING_INFOS_DISABLE_API=1` to force local-only lookups.
34
56
  - Added `genshinimpact`, `nte` (Neverness to Everness), and `honkaistarrail` games, each with `meta.json`.
35
57
  - Added all 104 currently-released Genshin Impact characters, all 20 currently-playable NTE characters, and all 69 currently-released Honkai: Star Rail characters under their respective `data/<game>/characters/` folders.
36
-