fansunited-data-layer 0.16.0 → 0.17.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 (71) hide show
  1. package/README.md +41 -0
  2. package/api/fansunited/index.d.ts +2 -2
  3. package/api/fansunited/index.d.ts.map +1 -1
  4. package/api/fansunited/search/__tests__/locale-agnostic-cache.test.d.ts +2 -0
  5. package/api/fansunited/search/__tests__/locale-agnostic-cache.test.d.ts.map +1 -0
  6. package/api/fansunited/search/index.d.ts.map +1 -1
  7. package/api/fansunited/search/index.js +41 -25
  8. package/api/fansunited/search/index.js.map +1 -1
  9. package/api/fansunited/search/transformer.js +3 -2
  10. package/api/fansunited/search/transformer.js.map +1 -1
  11. package/api/fansunited/sports/competition/__tests__/exports.test.d.ts +2 -0
  12. package/api/fansunited/sports/competition/__tests__/exports.test.d.ts.map +1 -0
  13. package/api/fansunited/sports/competition/__tests__/hydrated.test.d.ts +2 -0
  14. package/api/fansunited/sports/competition/__tests__/hydrated.test.d.ts.map +1 -0
  15. package/api/fansunited/sports/competition/__tests__/index.test.d.ts +2 -0
  16. package/api/fansunited/sports/competition/__tests__/index.test.d.ts.map +1 -0
  17. package/api/fansunited/sports/competition/hydrated.d.ts +45 -0
  18. package/api/fansunited/sports/competition/hydrated.d.ts.map +1 -0
  19. package/api/fansunited/sports/competition/hydrated.js +26 -0
  20. package/api/fansunited/sports/competition/hydrated.js.map +1 -0
  21. package/api/fansunited/sports/competition/index.d.ts +3 -12
  22. package/api/fansunited/sports/competition/index.d.ts.map +1 -1
  23. package/api/fansunited/sports/competition/index.js +16 -10
  24. package/api/fansunited/sports/competition/index.js.map +1 -1
  25. package/api/fansunited/sports/index.d.ts +6 -0
  26. package/api/fansunited/sports/index.d.ts.map +1 -1
  27. package/api/fansunited/sports/livescore/__tests__/hydrated.test.d.ts +2 -0
  28. package/api/fansunited/sports/livescore/__tests__/hydrated.test.d.ts.map +1 -0
  29. package/api/fansunited/sports/livescore/hydrated.d.ts +48 -0
  30. package/api/fansunited/sports/livescore/hydrated.d.ts.map +1 -0
  31. package/api/fansunited/sports/livescore/hydrated.js +34 -0
  32. package/api/fansunited/sports/livescore/hydrated.js.map +1 -0
  33. package/api/fansunited/sports/livescore/index.d.ts +27 -0
  34. package/api/fansunited/sports/livescore/index.d.ts.map +1 -0
  35. package/api/fansunited/sports/livescore/index.js +36 -0
  36. package/api/fansunited/sports/livescore/index.js.map +1 -0
  37. package/api/fansunited/sports/livescore/transformer.d.ts +8 -0
  38. package/api/fansunited/sports/livescore/transformer.d.ts.map +1 -0
  39. package/api/fansunited/sports/livescore/transformer.js +44 -0
  40. package/api/fansunited/sports/livescore/transformer.js.map +1 -0
  41. package/api/fansunited/sports/livescore/types.d.ts +58 -0
  42. package/api/fansunited/sports/livescore/types.d.ts.map +1 -0
  43. package/cache/__tests__/redis-integration.test.d.ts +14 -0
  44. package/cache/__tests__/redis-integration.test.d.ts.map +1 -0
  45. package/cache/__tests__/redis-l2-store.d.ts +52 -0
  46. package/cache/__tests__/redis-l2-store.d.ts.map +1 -0
  47. package/cache/__tests__/test-l2-store.d.ts +18 -0
  48. package/cache/__tests__/test-l2-store.d.ts.map +1 -0
  49. package/cache/cache-manager.d.ts +117 -12
  50. package/cache/cache-manager.d.ts.map +1 -1
  51. package/cache/cache-manager.js +23 -14
  52. package/cache/cache-manager.js.map +1 -1
  53. package/cache/cleanup.d.ts +1 -1
  54. package/cache/cleanup.d.ts.map +1 -1
  55. package/cache/index.d.ts +3 -2
  56. package/cache/index.d.ts.map +1 -1
  57. package/cache/sqlite-store.d.ts +4 -4
  58. package/cache/sqlite-store.d.ts.map +1 -1
  59. package/cache/types.d.ts +9 -1
  60. package/cache/types.d.ts.map +1 -1
  61. package/cache/types.js +5 -0
  62. package/cache/types.js.map +1 -0
  63. package/fansunited-data-layer.js +11 -1
  64. package/fansunited-data-layer.js.map +1 -1
  65. package/index.d.ts +5 -5
  66. package/index.d.ts.map +1 -1
  67. package/package.json +2 -1
  68. package/types/canonical/index.d.ts +1 -0
  69. package/types/canonical/index.d.ts.map +1 -1
  70. package/types/canonical/sports-livescore.types.d.ts +84 -0
  71. package/types/canonical/sports-livescore.types.d.ts.map +1 -0
package/README.md CHANGED
@@ -28,6 +28,47 @@ console.log(match.competitorOne.name); // "Manchester United"
28
28
  console.log(match.score?.competitorOne); // "2"
29
29
  ```
30
30
 
31
+ ## Caching & Hydration (new in v0.17)
32
+
33
+ The library ships a shared, SWR-backed cache for Sports API responses and a
34
+ `…Hydrated` family of functions that resolve every entity ID in a response
35
+ to its human-readable form (team names, logos, competition titles) in one
36
+ call.
37
+
38
+ ```typescript
39
+ import { getFansUnitedSportsCompetitionHydrated } from "fansunited-data-layer";
40
+
41
+ const board = await getFansUnitedSportsCompetitionHydrated("fb:c:1", {
42
+ locale: "EN",
43
+ });
44
+
45
+ for (const stage of board.season.stages) {
46
+ for (const group of stage.groups ?? []) {
47
+ for (const entry of group.standings) {
48
+ const team = board.entities.get(entry.competitorId);
49
+ console.log(`${entry.rank}. ${team?.name ?? entry.competitorId}`);
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ **Cache topology:**
56
+
57
+ - **L1** (in-process LRU, 50 MB) is always on.
58
+ - **L2** is opt-in via `initL2(store)` — typically Redis in a multi-instance
59
+ deployment so one warm cache serves every server. The adapter ships in
60
+ the consumer (browser bundles stay free of Node-only deps).
61
+ - **Stale-while-revalidate** TTLs per entity type — users almost never wait.
62
+ - **`fudl:`** prefix on every key so a shared Redis instance can be
63
+ inspected / cleared safely via `SCAN fudl:*`.
64
+
65
+ **For everything else** — the hydrated livescore variant, locale handling,
66
+ Redis wiring, TTL tuning, adding a new hydrated endpoint, troubleshooting —
67
+ read [`src/lib/cache/README.md`](src/lib/cache/README.md).
68
+
69
+ For the copy-paste template when adding a new hydrated Sports API endpoint,
70
+ read [`src/lib/api/fansunited/sports/README.md`](src/lib/api/fansunited/sports/README.md).
71
+
31
72
  ## API Reference
32
73
 
33
74
  ### Configuration
@@ -7,8 +7,8 @@
7
7
  export { getFansUnitedFootballCompetitions, getFansUnitedFootballCompetition, getFansUnitedFootballTeam, getFansUnitedFootballTeams, getFansUnitedFootballPlayer, getFansUnitedFootballPlayers, getFansUnitedFootballMatch, getFansUnitedFootballMatches, getFansUnitedFootballTeamNextMatch, getFansUnitedFootballTeamPreviousMatch, getFansUnitedFootballPlayerNextMatch, getFansUnitedFootballPlayerPreviousMatch, getFansUnitedFootballSearch, } from "./football";
8
8
  export type { GetFootballCompetitionsOptions, GetFootballCompetitionOptions, GetFootballTeamOptions, GetFootballTeamsOptions, GetFootballPlayerOptions, GetFootballPlayersOptions, GetFootballMatchOptions, GetFootballMatchesOptions, GetFootballSearchOptions, SearchEntityType, FansUnitedFootballSearchResult, } from "./football";
9
9
  export { getFansUnitedSearchEntities, getFansUnitedEntityById, getFansUnitedEntitiesByIds, getFansUnitedCompetitions, getFansUnitedTeamsByCountry, getFansUnitedTeamsByCompetition, getFansUnitedCountries, getFansUnitedVenues, } from "./search";
10
- export { getFansUnitedSportsCompetition } from "./sports";
11
- export type { GetSportsCompetitionOptions } from "./sports";
10
+ export { getFansUnitedSportsCompetition, getFansUnitedSportsCompetitionHydrated, getFansUnitedSportsLivescore, getFansUnitedSportsLivescoreHydrated, } from "./sports";
11
+ export type { GetSportsCompetitionOptions, GetSportsCompetitionHydratedOptions, GetSportsLivescoreOptions, GetSportsLivescoreHydratedOptions, FUSportsCompetitionHydrated, FUSportsLivescoreHydrated, } from "./sports";
12
12
  export type { SearchMode, EntityContentType, EntitySearchOptions, GetEntityByIdOptions, GetEntitiesByIdsOptions, GetCompetitionsOptions, GetTeamsByCountryOptions, GetTeamsByCompetitionOptions, GetCountriesOptions, GetVenuesOptions, RawSearchEntity, SearchEntityResult, SearchEntitySummary, EntitySearchResponse, PaginationMeta, PaginatedResult, } from "./search";
13
13
  export type { NextCacheOptions } from "./http";
14
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/api/fansunited/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACH,iCAAiC,EACjC,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,kCAAkC,EAClC,sCAAsC,EACtC,oCAAoC,EACpC,wCAAwC,EACxC,2BAA2B,GAC9B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACR,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,8BAA8B,GACjC,MAAM,YAAY,CAAC;AAGpB,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,mBAAmB,GACtB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAC1D,YAAY,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAE5D,YAAY,EACR,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,eAAe,GAClB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/api/fansunited/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACH,iCAAiC,EACjC,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,EAC1B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,kCAAkC,EAClC,sCAAsC,EACtC,oCAAoC,EACpC,wCAAwC,EACxC,2BAA2B,GAC9B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACR,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,gBAAgB,EAChB,8BAA8B,GACjC,MAAM,YAAY,CAAC;AAGpB,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,mBAAmB,GACtB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,8BAA8B,EAC9B,sCAAsC,EACtC,4BAA4B,EAC5B,oCAAoC,GACvC,MAAM,UAAU,CAAC;AAClB,YAAY,EACR,2BAA2B,EAC3B,mCAAmC,EACnC,yBAAyB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,yBAAyB,GAC5B,MAAM,UAAU,CAAC;AAElB,YAAY,EACR,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,eAAe,GAClB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=locale-agnostic-cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-agnostic-cache.test.d.ts","sourceRoot":"","sources":["../../../../../src/lib/api/fansunited/search/__tests__/locale-agnostic-cache.test.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/fansunited/search/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,OAAO,KAAK,EACR,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAGhB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACtB,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACvB,MAAM,qCAAqC,CAAC;AAgK7C;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,OAAO,GAAE,mBAAwB,EACjC,MAAM,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAA;CAAE,GAChD,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAqC/C;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CACzC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAuB7B;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC5C,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkC/B;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC3C,OAAO,GAAE,sBAA2B,GACrC,OAAO,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC,CA2BtD;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CA6B/C;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CACjD,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,4BAAiC,GAC3C,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CA6B/C;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CACxC,OAAO,GAAE,mBAAwB,GAClC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC,CA0BlD;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,CA2BhD;AAGD,YAAY,EACR,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/fansunited/search/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,OAAO,KAAK,EACR,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAGhB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACtB,MAAM,SAAS,CAAC;AAGjB,OAAO,KAAK,EACR,0BAA0B,EAC1B,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACvB,MAAM,qCAAqC,CAAC;AAqM7C;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,OAAO,GAAE,mBAAwB,EACjC,MAAM,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAA;CAAE,GAChD,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAqC/C;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CACzC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,oBAAoB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAuB7B;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC5C,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAgC/B;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC3C,OAAO,GAAE,sBAA2B,GACrC,OAAO,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC,CA2BtD;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC7C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,wBAA6B,GACvC,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CA6B/C;AAED;;;GAGG;AACH,wBAAsB,+BAA+B,CACjD,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,4BAAiC,GAC3C,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CA6B/C;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CACxC,OAAO,GAAE,mBAAwB,GAClC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC,CA0BlD;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,GAAE,gBAAqB,GAC/B,OAAO,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,CA2BhD;AAGD,YAAY,EACR,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,SAAS,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { searchHttp } from "./http.js";
2
2
  import { isConfigured, getConfig } from "../../../config/index.js";
3
3
  import { transformCompetitionSummary, transformCountrySummary, transformEntity, transformEntitySummary, transformTeamSummary, transformVenueSummary } from "./transformer.js";
4
+ import { CACHE_KEY_PREFIX } from "../../../cache/types.js";
4
5
  import { cached, cachedBatch } from "../../../cache/cache-manager.js";
5
6
  import { memoryStore } from "../../../cache/memory-store.js";
6
7
  function hashParams(params) {
@@ -14,7 +15,7 @@ function hashParams(params) {
14
15
  function cacheIndividualEntities(entities) {
15
16
  for (const entity of entities) {
16
17
  if (entity.id) {
17
- memoryStore.set(`entity:${entity.id}`, entity);
18
+ memoryStore.set(`${CACHE_KEY_PREFIX}entity:${entity.id}`, entity);
18
19
  }
19
20
  }
20
21
  }
@@ -35,28 +36,45 @@ function collectMissingIds(entities) {
35
36
  const related = raw.related;
36
37
  if (related) {
37
38
  for (const r of related) {
38
- if (!memoryStore.get(`entity:${r.related_id}`)) {
39
+ if (!memoryStore.get(`${CACHE_KEY_PREFIX}entity:${r.related_id}`)) {
39
40
  missingIds.add(r.related_id);
40
41
  }
41
42
  }
42
43
  }
43
44
  const countryId = raw.country_id;
44
- if (countryId && !memoryStore.get(`entity:${countryId}`)) {
45
+ if (countryId && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${countryId}`)) {
45
46
  missingIds.add(countryId);
46
47
  }
47
48
  }
48
49
  return missingIds;
49
50
  }
51
+ const SEARCH_API_MAX_LIMIT = 100;
52
+ async function fetchEntitiesByIds(ids, fetchOptions) {
53
+ if (ids.length === 0) return [];
54
+ const chunks = [];
55
+ for (let i = 0; i < ids.length; i += SEARCH_API_MAX_LIMIT) {
56
+ chunks.push(ids.slice(i, i + SEARCH_API_MAX_LIMIT));
57
+ }
58
+ const responses = await Promise.all(
59
+ chunks.map(
60
+ (chunk) => searchHttp.get({
61
+ path: "/v1/entities/search",
62
+ params: {
63
+ ids: chunk,
64
+ limit: String(chunk.length)
65
+ },
66
+ next: fetchOptions?.next,
67
+ config: fetchOptions?.config
68
+ })
69
+ )
70
+ );
71
+ return responses.flatMap((r) => r.data);
72
+ }
50
73
  async function batchFetchAndCache(ids, fetchOptions) {
51
74
  if (ids.size === 0) return [];
52
- const response = await searchHttp.get({
53
- path: "/v1/entities/search",
54
- params: { ids: Array.from(ids) },
55
- next: fetchOptions?.next,
56
- config: fetchOptions?.config
57
- });
58
- cacheIndividualEntities(response.data);
59
- return response.data;
75
+ const data = await fetchEntitiesByIds(Array.from(ids), fetchOptions);
76
+ cacheIndividualEntities(data);
77
+ return data;
60
78
  }
61
79
  async function prefetchRelatedEntities(entities, fetchOptions) {
62
80
  const pass1Ids = collectMissingIds(entities);
@@ -75,13 +93,13 @@ async function prefetchCountries(entities, fetchOptions) {
75
93
  for (const entity of entities) {
76
94
  const raw = entity;
77
95
  const countryId = raw.country_id;
78
- if (countryId && !memoryStore.get(`entity:${countryId}`)) {
96
+ if (countryId && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${countryId}`)) {
79
97
  missingIds.add(countryId);
80
98
  }
81
99
  const related = raw.related;
82
100
  if (related) {
83
101
  for (const r of related) {
84
- if (r.relationship === "COUNTRY" && !memoryStore.get(`entity:${r.related_id}`)) {
102
+ if (r.relationship === "COUNTRY" && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${r.related_id}`)) {
85
103
  missingIds.add(r.related_id);
86
104
  }
87
105
  }
@@ -106,7 +124,7 @@ async function getFansUnitedSearchEntities(options = {}, config) {
106
124
  relationship: options.relationship,
107
125
  value: options.value
108
126
  };
109
- const cacheKey = `search:entities:${hashParams(params)}`;
127
+ const cacheKey = `${CACHE_KEY_PREFIX}search:entities:${hashParams(params)}`;
110
128
  const result = await cached(
111
129
  cacheKey,
112
130
  "search",
@@ -126,7 +144,7 @@ async function getFansUnitedSearchEntities(options = {}, config) {
126
144
  }
127
145
  async function getFansUnitedEntityById(id, options) {
128
146
  const lang = resolveLanguage(options);
129
- const cacheKey = `entity:${id}`;
147
+ const cacheKey = `${CACHE_KEY_PREFIX}entity:${id}`;
130
148
  const raw = await cached(cacheKey, "search", async () => {
131
149
  const response = await searchHttp.get({
132
150
  path: "/v1/entities/search",
@@ -149,19 +167,17 @@ async function getFansUnitedEntitiesByIds(ids, options) {
149
167
  ids,
150
168
  "search",
151
169
  async (missingIds) => {
152
- const response = await searchHttp.get({
153
- path: "/v1/entities/search",
154
- params: { ids: missingIds },
170
+ const fetched = await fetchEntitiesByIds(missingIds, {
155
171
  next: options?.next,
156
172
  config: options?.config
157
173
  });
158
174
  const map = /* @__PURE__ */ new Map();
159
- for (const entity of response.data) {
175
+ for (const entity of fetched) {
160
176
  map.set(entity.id, entity);
161
177
  }
162
178
  return map;
163
179
  },
164
- (id) => `entity:${id}`
180
+ (id) => `${CACHE_KEY_PREFIX}entity:${id}`
165
181
  );
166
182
  const rawEntities = ids.map((id) => resultsMap.get(id)).filter((e) => e !== void 0);
167
183
  await prefetchRelatedEntities(rawEntities, { next: options?.next, config: options?.config });
@@ -176,7 +192,7 @@ async function getFansUnitedCompetitions(options = {}) {
176
192
  page: options.page?.toString(),
177
193
  sport: options.sport
178
194
  };
179
- const cacheKey = `competitions:${hashParams(params)}`;
195
+ const cacheKey = `${CACHE_KEY_PREFIX}competitions:${hashParams(params)}`;
180
196
  const result = await cached(
181
197
  cacheKey,
182
198
  "competitions",
@@ -203,7 +219,7 @@ async function getFansUnitedTeamsByCountry(countryId, options = {}) {
203
219
  page: options.page?.toString(),
204
220
  sport: options.sport
205
221
  };
206
- const cacheKey = `teams:country:${countryId}:${hashParams(params)}`;
222
+ const cacheKey = `${CACHE_KEY_PREFIX}teams:country:${countryId}:${hashParams(params)}`;
207
223
  const result = await cached(
208
224
  cacheKey,
209
225
  "teams",
@@ -230,7 +246,7 @@ async function getFansUnitedTeamsByCompetition(competitionId, options = {}) {
230
246
  page: options.page?.toString(),
231
247
  sport: options.sport
232
248
  };
233
- const cacheKey = `teams:competition:${competitionId}:${hashParams(params)}`;
249
+ const cacheKey = `${CACHE_KEY_PREFIX}teams:competition:${competitionId}:${hashParams(params)}`;
234
250
  const result = await cached(
235
251
  cacheKey,
236
252
  "teams",
@@ -255,7 +271,7 @@ async function getFansUnitedCountries(options = {}) {
255
271
  page: options.page?.toString(),
256
272
  sport: options.sport
257
273
  };
258
- const cacheKey = `countries:${hashParams(params)}`;
274
+ const cacheKey = `${CACHE_KEY_PREFIX}countries:${hashParams(params)}`;
259
275
  const result = await cached(
260
276
  cacheKey,
261
277
  "countries",
@@ -279,7 +295,7 @@ async function getFansUnitedVenues(options = {}) {
279
295
  page: options.page?.toString(),
280
296
  sport: options.sport
281
297
  };
282
- const cacheKey = `venues:${hashParams(params)}`;
298
+ const cacheKey = `${CACHE_KEY_PREFIX}venues:${hashParams(params)}`;
283
299
  const result = await cached(
284
300
  cacheKey,
285
301
  "venues",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/lib/api/fansunited/search/index.ts"],"sourcesContent":["/**\n * Fans United Search API - Public functions with caching\n */\n\nimport { searchHttp } from \"./http\";\nimport { cached, cachedBatch, memoryStore } from \"../../../cache\";\nimport { getConfig, isConfigured } from \"../../../config\";\nimport {\n transformEntity,\n transformEntitySummary,\n transformCompetitionSummary,\n transformTeamSummary,\n transformCountrySummary,\n transformVenueSummary,\n} from \"./transformer\";\nimport type { RawCompetition, RawTeam, RawCountry, RawVenue, RawSearchEntityBase, RawRelated } from \"./raw-types\";\nimport type {\n EntitySearchOptions,\n GetEntityByIdOptions,\n GetEntitiesByIdsOptions,\n GetCompetitionsOptions,\n GetTeamsByCountryOptions,\n GetTeamsByCompetitionOptions,\n GetCountriesOptions,\n GetVenuesOptions,\n RawSearchEntity,\n EntitySearchResponse,\n PaginatedResult,\n SearchEntityResult,\n SearchEntitySummary,\n} from \"./types\";\nimport type { NextCacheOptions } from \"../http\";\nimport type { DataLayerConfig } from \"../../../config\";\nimport type {\n FUSportsCompetitionSummary,\n FUSportsTeamSummary,\n FUSportsCountrySummary,\n FUSportsVenueSummary,\n} from \"../../../types/canonical/base.types\";\n\nfunction hashParams(params: Record<string, string | string[] | undefined>): string {\n const sorted = Object.entries(params)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=${Array.isArray(v) ? v.join(\",\") : v}`)\n .join(\"&\");\n // Simple hash — sufficient for cache key uniqueness\n let hash = 0;\n for (let i = 0; i < sorted.length; i++) {\n hash = ((hash << 5) - hash + sorted.charCodeAt(i)) | 0;\n }\n return hash.toString(36);\n}\n\n/** Cache individual entities from a search response for later ID lookups */\nfunction cacheIndividualEntities(entities: RawSearchEntity[]): void {\n for (const entity of entities) {\n if (entity.id) {\n memoryStore.set(`entity:${entity.id}`, entity);\n }\n }\n}\n\n/**\n * Resolve the language for transformation.\n * Priority: options.lang → config.fansUnited.lang → \"EN\"\n */\nfunction resolveLanguage(options?: { lang?: string }): string {\n if (options?.lang) return options.lang;\n if (isConfigured()) {\n const config = getConfig();\n if (config.fansUnited && \"lang\" in config.fansUnited && config.fansUnited.lang) {\n return config.fansUnited.lang;\n }\n }\n return \"EN\";\n}\n\n/**\n * Collect missing related entity IDs (and country_id fields) from raw entities.\n */\nfunction collectMissingIds(entities: RawSearchEntity[]): Set<string> {\n const missingIds = new Set<string>();\n\n for (const entity of entities) {\n const raw = entity as Record<string, unknown>;\n\n // Collect related IDs\n const related = raw.related as RawRelated[] | undefined;\n if (related) {\n for (const r of related) {\n if (!memoryStore.get(`entity:${r.related_id}`)) {\n missingIds.add(r.related_id);\n }\n }\n }\n\n // Collect country_id\n const countryId = raw.country_id as string | undefined;\n if (countryId && !memoryStore.get(`entity:${countryId}`)) {\n missingIds.add(countryId);\n }\n }\n\n return missingIds;\n}\n\n/**\n * Batch-fetch entity IDs from the search API and cache the results.\n * Returns the fetched raw entities.\n */\nasync function batchFetchAndCache(\n ids: Set<string>,\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<RawSearchEntity[]> {\n if (ids.size === 0) return [];\n\n const response = await searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params: { ids: Array.from(ids) },\n next: fetchOptions?.next,\n config: fetchOptions?.config,\n });\n cacheIndividualEntities(response.data);\n return response.data;\n}\n\n/**\n * Collect all related entity IDs (and country_id fields) from raw entities\n * that are not already in cache, then batch-fetch them.\n * Does a two-pass fetch: after the first fetch, checks the newly fetched\n * entities for their own dependencies (e.g. country_ids) and fetches those too.\n */\nasync function prefetchRelatedEntities(\n entities: RawSearchEntity[],\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<void> {\n // Pass 1: fetch related entities and country_ids from top-level entities\n const pass1Ids = collectMissingIds(entities);\n if (pass1Ids.size === 0) return;\n\n try {\n const fetched = await batchFetchAndCache(pass1Ids, fetchOptions);\n\n // Pass 2: fetch dependencies of the newly fetched entities\n // (e.g. country_ids of related competitions/teams)\n const pass2Ids = collectMissingIds(fetched);\n if (pass2Ids.size > 0) {\n await batchFetchAndCache(pass2Ids, fetchOptions);\n }\n } catch {\n // Prefetch is best-effort — if it fails, the transformer\n // will produce partial results for uncached related entities\n }\n}\n\n/**\n * Lightweight prefetch — only country_ids (single pass).\n * Used by list/search functions that return summary types.\n */\nasync function prefetchCountries(\n entities: RawSearchEntity[],\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<void> {\n const missingIds = new Set<string>();\n\n for (const entity of entities) {\n const raw = entity as Record<string, unknown>;\n\n const countryId = raw.country_id as string | undefined;\n if (countryId && !memoryStore.get(`entity:${countryId}`)) {\n missingIds.add(countryId);\n }\n\n // Also check related array for COUNTRY entries\n const related = raw.related as RawRelated[] | undefined;\n if (related) {\n for (const r of related) {\n if (r.relationship === \"COUNTRY\" && !memoryStore.get(`entity:${r.related_id}`)) {\n missingIds.add(r.related_id);\n }\n }\n }\n }\n\n if (missingIds.size === 0) return;\n\n try {\n await batchFetchAndCache(missingIds, fetchOptions);\n } catch {\n // Best-effort — summary transforms will produce partial country data\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Search entities across all content types.\n * Returns transformed canonical types.\n */\nexport async function getFansUnitedSearchEntities(\n options: EntitySearchOptions = {},\n config?: { next?: EntitySearchOptions[\"next\"] }\n): Promise<PaginatedResult<SearchEntitySummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | string[] | undefined> = {\n query: options.query,\n content_type: options.contentType,\n ids: options.ids,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n mode: options.mode,\n sport: options.sport,\n relationship: options.relationship,\n value: options.value,\n };\n\n const cacheKey = `search:entities:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"search\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next || config?.next,\n config: options.config,\n })\n );\n\n // Side-cache individual entities (raw)\n cacheIndividualEntities(result.data);\n\n // Pre-fetch only countries (lightweight, single pass)\n await prefetchCountries(result.data, { next: options.next || config?.next, config: options.config });\n\n // Transform each raw entity to its summary type (no related, no providerRef)\n const transformed = result.data.map((e) =>\n transformEntitySummary(e as RawSearchEntityBase & Record<string, unknown>, lang)\n );\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get a single entity by ID.\n * Returns transformed canonical type.\n */\nexport async function getFansUnitedEntityById(\n id: string,\n options?: GetEntityByIdOptions\n): Promise<SearchEntityResult> {\n const lang = resolveLanguage(options);\n const cacheKey = `entity:${id}`;\n\n const raw = await cached<RawSearchEntity>(cacheKey, \"search\", async () => {\n const response = await searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params: { ids: [id] },\n next: options?.next,\n config: options?.config,\n });\n\n if (!response.data || response.data.length === 0) {\n throw new Error(`Entity not found: ${id}`);\n }\n\n return response.data[0];\n });\n\n // Pre-fetch related entities for this single entity\n await prefetchRelatedEntities([raw], { next: options?.next, config: options?.config });\n\n return transformEntity(raw as RawSearchEntityBase & Record<string, unknown>, lang);\n}\n\n/**\n * Get multiple entities by IDs — smart batch caching.\n * Only fetches uncached IDs from the API.\n * Returns transformed canonical types.\n */\nexport async function getFansUnitedEntitiesByIds(\n ids: string[],\n options?: GetEntitiesByIdsOptions\n): Promise<SearchEntityResult[]> {\n if (ids.length === 0) return [];\n\n const lang = resolveLanguage(options);\n\n const resultsMap = await cachedBatch<RawSearchEntity>(\n ids,\n \"search\",\n async (missingIds) => {\n const response = await searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params: { ids: missingIds },\n next: options?.next,\n config: options?.config,\n });\n\n const map = new Map<string, RawSearchEntity>();\n for (const entity of response.data) {\n map.set(entity.id, entity);\n }\n return map;\n },\n (id) => `entity:${id}`\n );\n\n // Collect raw entities in order\n const rawEntities = ids\n .map((id) => resultsMap.get(id))\n .filter((e): e is RawSearchEntity => e !== undefined);\n\n // Pre-fetch related entities\n await prefetchRelatedEntities(rawEntities, { next: options?.next, config: options?.config });\n\n return rawEntities.map((e) => transformEntity(e as RawSearchEntityBase & Record<string, unknown>, lang));\n}\n\n/**\n * Get competitions with optional filtering.\n * Returns transformed FUSportsCompetition objects.\n */\nexport async function getFansUnitedCompetitions(\n options: GetCompetitionsOptions = {}\n): Promise<PaginatedResult<FUSportsCompetitionSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"competition\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `competitions:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"competitions\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformCompetitionSummary(e as unknown as RawCompetition, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get teams filtered by country.\n * Returns transformed FUSportsTeamCompetitor objects.\n */\nexport async function getFansUnitedTeamsByCountry(\n countryId: string,\n options: GetTeamsByCountryOptions = {}\n): Promise<PaginatedResult<FUSportsTeamSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"team\",\n relationship: \"COUNTRY\",\n value: countryId,\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `teams:country:${countryId}:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"teams\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformTeamSummary(e as unknown as RawTeam, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get teams filtered by competition.\n * Returns transformed FUSportsTeamCompetitor objects.\n */\nexport async function getFansUnitedTeamsByCompetition(\n competitionId: string,\n options: GetTeamsByCompetitionOptions = {}\n): Promise<PaginatedResult<FUSportsTeamSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"team\",\n relationship: \"COMPETITION\",\n value: competitionId,\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `teams:competition:${competitionId}:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"teams\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformTeamSummary(e as unknown as RawTeam, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get countries with optional filtering.\n * Returns transformed FUSportsCountry objects.\n */\nexport async function getFansUnitedCountries(\n options: GetCountriesOptions = {}\n): Promise<PaginatedResult<FUSportsCountrySummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"country\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `countries:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"countries\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n\n const transformed = result.data.map((e) => transformCountrySummary(e as unknown as RawCountry, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get venues with optional filtering.\n * Returns transformed FUSportsVenue objects.\n */\nexport async function getFansUnitedVenues(\n options: GetVenuesOptions = {}\n): Promise<PaginatedResult<FUSportsVenueSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"venue\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `venues:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"venues\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformVenueSummary(e as unknown as RawVenue, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n// Re-export types\nexport type {\n SearchMode,\n EntityContentType,\n EntitySearchOptions,\n GetEntityByIdOptions,\n GetEntitiesByIdsOptions,\n GetCompetitionsOptions,\n GetTeamsByCountryOptions,\n GetTeamsByCompetitionOptions,\n GetCountriesOptions,\n GetVenuesOptions,\n RawSearchEntity,\n EntitySearchResponse,\n PaginationMeta,\n PaginatedResult,\n SearchEntityResult,\n SearchEntitySummary,\n} from \"./types\";\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/lib/api/fansunited/search/index.ts"],"sourcesContent":["/**\n * Fans United Search API - Public functions with caching\n */\n\nimport { searchHttp } from \"./http\";\nimport { cached, cachedBatch, memoryStore, CACHE_KEY_PREFIX } from \"../../../cache\";\nimport { getConfig, isConfigured } from \"../../../config\";\nimport {\n transformEntity,\n transformEntitySummary,\n transformCompetitionSummary,\n transformTeamSummary,\n transformCountrySummary,\n transformVenueSummary,\n} from \"./transformer\";\nimport type { RawCompetition, RawTeam, RawCountry, RawVenue, RawSearchEntityBase, RawRelated } from \"./raw-types\";\nimport type {\n EntitySearchOptions,\n GetEntityByIdOptions,\n GetEntitiesByIdsOptions,\n GetCompetitionsOptions,\n GetTeamsByCountryOptions,\n GetTeamsByCompetitionOptions,\n GetCountriesOptions,\n GetVenuesOptions,\n RawSearchEntity,\n EntitySearchResponse,\n PaginatedResult,\n SearchEntityResult,\n SearchEntitySummary,\n} from \"./types\";\nimport type { NextCacheOptions } from \"../http\";\nimport type { DataLayerConfig } from \"../../../config\";\nimport type {\n FUSportsCompetitionSummary,\n FUSportsTeamSummary,\n FUSportsCountrySummary,\n FUSportsVenueSummary,\n} from \"../../../types/canonical/base.types\";\n\nfunction hashParams(params: Record<string, string | string[] | undefined>): string {\n const sorted = Object.entries(params)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=${Array.isArray(v) ? v.join(\",\") : v}`)\n .join(\"&\");\n // Simple hash — sufficient for cache key uniqueness\n let hash = 0;\n for (let i = 0; i < sorted.length; i++) {\n hash = ((hash << 5) - hash + sorted.charCodeAt(i)) | 0;\n }\n return hash.toString(36);\n}\n\n/** Cache individual entities from a search response for later ID lookups */\nfunction cacheIndividualEntities(entities: RawSearchEntity[]): void {\n for (const entity of entities) {\n if (entity.id) {\n memoryStore.set(`${CACHE_KEY_PREFIX}entity:${entity.id}`, entity);\n }\n }\n}\n\n/**\n * Resolve the language for transformation.\n * Priority: options.lang → config.fansUnited.lang → \"EN\"\n */\nfunction resolveLanguage(options?: { lang?: string }): string {\n if (options?.lang) return options.lang;\n if (isConfigured()) {\n const config = getConfig();\n if (config.fansUnited && \"lang\" in config.fansUnited && config.fansUnited.lang) {\n return config.fansUnited.lang;\n }\n }\n return \"EN\";\n}\n\n/**\n * Collect missing related entity IDs (and country_id fields) from raw entities.\n */\nfunction collectMissingIds(entities: RawSearchEntity[]): Set<string> {\n const missingIds = new Set<string>();\n\n for (const entity of entities) {\n const raw = entity as Record<string, unknown>;\n\n // Collect related IDs\n const related = raw.related as RawRelated[] | undefined;\n if (related) {\n for (const r of related) {\n if (!memoryStore.get(`${CACHE_KEY_PREFIX}entity:${r.related_id}`)) {\n missingIds.add(r.related_id);\n }\n }\n }\n\n // Collect country_id\n const countryId = raw.country_id as string | undefined;\n if (countryId && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${countryId}`)) {\n missingIds.add(countryId);\n }\n }\n\n return missingIds;\n}\n\n/**\n * Search API `limit` parameter caps at 100 (and defaults to 10 if unset).\n * Passing more than 100 IDs in one request would silently drop everything\n * beyond the page limit — so we chunk and fan-out in parallel.\n */\nconst SEARCH_API_MAX_LIMIT = 100;\n\n/**\n * Fetch raw entities by ID, working around the Search API's pagination cap.\n *\n * - Always passes `limit` equal to the chunk size, so the API never silently\n * trims the response to its default page size (10).\n * - Splits requests of >100 IDs into parallel chunks of ≤100.\n */\nasync function fetchEntitiesByIds(\n ids: string[],\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<RawSearchEntity[]> {\n if (ids.length === 0) return [];\n\n const chunks: string[][] = [];\n for (let i = 0; i < ids.length; i += SEARCH_API_MAX_LIMIT) {\n chunks.push(ids.slice(i, i + SEARCH_API_MAX_LIMIT));\n }\n\n const responses = await Promise.all(\n chunks.map((chunk) =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params: {\n ids: chunk,\n limit: String(chunk.length),\n },\n next: fetchOptions?.next,\n config: fetchOptions?.config,\n })\n )\n );\n\n return responses.flatMap((r) => r.data);\n}\n\n/**\n * Batch-fetch entity IDs from the search API and cache the results.\n * Returns the fetched raw entities.\n */\nasync function batchFetchAndCache(\n ids: Set<string>,\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<RawSearchEntity[]> {\n if (ids.size === 0) return [];\n\n const data = await fetchEntitiesByIds(Array.from(ids), fetchOptions);\n cacheIndividualEntities(data);\n return data;\n}\n\n/**\n * Collect all related entity IDs (and country_id fields) from raw entities\n * that are not already in cache, then batch-fetch them.\n * Does a two-pass fetch: after the first fetch, checks the newly fetched\n * entities for their own dependencies (e.g. country_ids) and fetches those too.\n */\nasync function prefetchRelatedEntities(\n entities: RawSearchEntity[],\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<void> {\n // Pass 1: fetch related entities and country_ids from top-level entities\n const pass1Ids = collectMissingIds(entities);\n if (pass1Ids.size === 0) return;\n\n try {\n const fetched = await batchFetchAndCache(pass1Ids, fetchOptions);\n\n // Pass 2: fetch dependencies of the newly fetched entities\n // (e.g. country_ids of related competitions/teams)\n const pass2Ids = collectMissingIds(fetched);\n if (pass2Ids.size > 0) {\n await batchFetchAndCache(pass2Ids, fetchOptions);\n }\n } catch {\n // Prefetch is best-effort — if it fails, the transformer\n // will produce partial results for uncached related entities\n }\n}\n\n/**\n * Lightweight prefetch — only country_ids (single pass).\n * Used by list/search functions that return summary types.\n */\nasync function prefetchCountries(\n entities: RawSearchEntity[],\n fetchOptions?: { next?: NextCacheOptions; config?: DataLayerConfig }\n): Promise<void> {\n const missingIds = new Set<string>();\n\n for (const entity of entities) {\n const raw = entity as Record<string, unknown>;\n\n const countryId = raw.country_id as string | undefined;\n if (countryId && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${countryId}`)) {\n missingIds.add(countryId);\n }\n\n // Also check related array for COUNTRY entries\n const related = raw.related as RawRelated[] | undefined;\n if (related) {\n for (const r of related) {\n if (r.relationship === \"COUNTRY\" && !memoryStore.get(`${CACHE_KEY_PREFIX}entity:${r.related_id}`)) {\n missingIds.add(r.related_id);\n }\n }\n }\n }\n\n if (missingIds.size === 0) return;\n\n try {\n await batchFetchAndCache(missingIds, fetchOptions);\n } catch {\n // Best-effort — summary transforms will produce partial country data\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Search entities across all content types.\n * Returns transformed canonical types.\n */\nexport async function getFansUnitedSearchEntities(\n options: EntitySearchOptions = {},\n config?: { next?: EntitySearchOptions[\"next\"] }\n): Promise<PaginatedResult<SearchEntitySummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | string[] | undefined> = {\n query: options.query,\n content_type: options.contentType,\n ids: options.ids,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n mode: options.mode,\n sport: options.sport,\n relationship: options.relationship,\n value: options.value,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}search:entities:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"search\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next || config?.next,\n config: options.config,\n })\n );\n\n // Side-cache individual entities (raw)\n cacheIndividualEntities(result.data);\n\n // Pre-fetch only countries (lightweight, single pass)\n await prefetchCountries(result.data, { next: options.next || config?.next, config: options.config });\n\n // Transform each raw entity to its summary type (no related, no providerRef)\n const transformed = result.data.map((e) =>\n transformEntitySummary(e as RawSearchEntityBase & Record<string, unknown>, lang)\n );\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get a single entity by ID.\n * Returns transformed canonical type.\n */\nexport async function getFansUnitedEntityById(\n id: string,\n options?: GetEntityByIdOptions\n): Promise<SearchEntityResult> {\n const lang = resolveLanguage(options);\n const cacheKey = `${CACHE_KEY_PREFIX}entity:${id}`;\n\n const raw = await cached<RawSearchEntity>(cacheKey, \"search\", async () => {\n const response = await searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params: { ids: [id] },\n next: options?.next,\n config: options?.config,\n });\n\n if (!response.data || response.data.length === 0) {\n throw new Error(`Entity not found: ${id}`);\n }\n\n return response.data[0];\n });\n\n // Pre-fetch related entities for this single entity\n await prefetchRelatedEntities([raw], { next: options?.next, config: options?.config });\n\n return transformEntity(raw as RawSearchEntityBase & Record<string, unknown>, lang);\n}\n\n/**\n * Get multiple entities by IDs — smart batch caching.\n * Only fetches uncached IDs from the API.\n * Returns transformed canonical types.\n */\nexport async function getFansUnitedEntitiesByIds(\n ids: string[],\n options?: GetEntitiesByIdsOptions\n): Promise<SearchEntityResult[]> {\n if (ids.length === 0) return [];\n\n const lang = resolveLanguage(options);\n\n const resultsMap = await cachedBatch<RawSearchEntity>(\n ids,\n \"search\",\n async (missingIds) => {\n const fetched = await fetchEntitiesByIds(missingIds, {\n next: options?.next,\n config: options?.config,\n });\n\n const map = new Map<string, RawSearchEntity>();\n for (const entity of fetched) {\n map.set(entity.id, entity);\n }\n return map;\n },\n (id) => `${CACHE_KEY_PREFIX}entity:${id}`\n );\n\n // Collect raw entities in order\n const rawEntities = ids\n .map((id) => resultsMap.get(id))\n .filter((e): e is RawSearchEntity => e !== undefined);\n\n // Pre-fetch related entities\n await prefetchRelatedEntities(rawEntities, { next: options?.next, config: options?.config });\n\n return rawEntities.map((e) => transformEntity(e as RawSearchEntityBase & Record<string, unknown>, lang));\n}\n\n/**\n * Get competitions with optional filtering.\n * Returns transformed FUSportsCompetition objects.\n */\nexport async function getFansUnitedCompetitions(\n options: GetCompetitionsOptions = {}\n): Promise<PaginatedResult<FUSportsCompetitionSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"competition\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}competitions:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"competitions\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformCompetitionSummary(e as unknown as RawCompetition, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get teams filtered by country.\n * Returns transformed FUSportsTeamCompetitor objects.\n */\nexport async function getFansUnitedTeamsByCountry(\n countryId: string,\n options: GetTeamsByCountryOptions = {}\n): Promise<PaginatedResult<FUSportsTeamSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"team\",\n relationship: \"COUNTRY\",\n value: countryId,\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}teams:country:${countryId}:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"teams\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformTeamSummary(e as unknown as RawTeam, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get teams filtered by competition.\n * Returns transformed FUSportsTeamCompetitor objects.\n */\nexport async function getFansUnitedTeamsByCompetition(\n competitionId: string,\n options: GetTeamsByCompetitionOptions = {}\n): Promise<PaginatedResult<FUSportsTeamSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"team\",\n relationship: \"COMPETITION\",\n value: competitionId,\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}teams:competition:${competitionId}:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"teams\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformTeamSummary(e as unknown as RawTeam, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get countries with optional filtering.\n * Returns transformed FUSportsCountry objects.\n */\nexport async function getFansUnitedCountries(\n options: GetCountriesOptions = {}\n): Promise<PaginatedResult<FUSportsCountrySummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"country\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}countries:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"countries\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n\n const transformed = result.data.map((e) => transformCountrySummary(e as unknown as RawCountry, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n/**\n * Get venues with optional filtering.\n * Returns transformed FUSportsVenue objects.\n */\nexport async function getFansUnitedVenues(\n options: GetVenuesOptions = {}\n): Promise<PaginatedResult<FUSportsVenueSummary>> {\n const lang = resolveLanguage(options);\n const params: Record<string, string | undefined> = {\n content_type: \"venue\",\n query: options.query,\n limit: options.limit?.toString(),\n page: options.page?.toString(),\n sport: options.sport,\n };\n\n const cacheKey = `${CACHE_KEY_PREFIX}venues:${hashParams(params)}`;\n\n const result = await cached<EntitySearchResponse>(cacheKey, \"venues\", () =>\n searchHttp.get<EntitySearchResponse>({\n path: \"/v1/entities/search\",\n params,\n next: options.next,\n config: options.config,\n })\n );\n\n cacheIndividualEntities(result.data);\n await prefetchCountries(result.data, { next: options.next, config: options.config });\n\n const transformed = result.data.map((e) => transformVenueSummary(e as unknown as RawVenue, lang));\n\n return { data: transformed, pagination: result.meta.pagination };\n}\n\n// Re-export types\nexport type {\n SearchMode,\n EntityContentType,\n EntitySearchOptions,\n GetEntityByIdOptions,\n GetEntitiesByIdsOptions,\n GetCompetitionsOptions,\n GetTeamsByCountryOptions,\n GetTeamsByCompetitionOptions,\n GetCountriesOptions,\n GetVenuesOptions,\n RawSearchEntity,\n EntitySearchResponse,\n PaginationMeta,\n PaginatedResult,\n SearchEntityResult,\n SearchEntitySummary,\n} from \"./types\";\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { memoryStore } from "../../../cache/memory-store.js";
2
+ import { CACHE_KEY_PREFIX } from "../../../cache/types.js";
2
3
  function resolveTranslation(translations, lang, fallbackName, fallbackShortName) {
3
4
  const upperLang = lang.toUpperCase();
4
5
  const target = translations.find((t) => t.language.toUpperCase() === upperLang);
@@ -50,7 +51,7 @@ function getRelatedIds(related, relationship) {
50
51
  function resolveCountry(countryId, related, lang) {
51
52
  const id = countryId || getRelatedIds(related, "COUNTRY")[0];
52
53
  if (!id) return void 0;
53
- const cachedEntry = memoryStore.get(id) ?? memoryStore.get(`entity:${id}`);
54
+ const cachedEntry = memoryStore.get(id) ?? memoryStore.get(`${CACHE_KEY_PREFIX}entity:${id}`);
54
55
  if (cachedEntry?.data) {
55
56
  const raw = cachedEntry.data;
56
57
  return transformCountrySummary(raw, lang);
@@ -153,7 +154,7 @@ function transformCoachSummary(raw, lang) {
153
154
  };
154
155
  }
155
156
  function hydrateRelatedEntity(id, relationship, lang) {
156
- const entry = memoryStore.get(id) ?? memoryStore.get(`entity:${id}`);
157
+ const entry = memoryStore.get(id) ?? memoryStore.get(`${CACHE_KEY_PREFIX}entity:${id}`);
157
158
  if (!entry?.data) return void 0;
158
159
  const raw = entry.data;
159
160
  switch (relationship) {
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.js","sources":["../../../../src/lib/api/fansunited/search/transformer.ts"],"sourcesContent":["/**\n * Raw → Canonical transformer for Search API entities.\n *\n * Resolves translations to a target language (with EN fallback),\n * maps raw snake_case fields to canonical camelCase types,\n * and hydrates related entries (country + related) one level deep from cache.\n */\n\nimport { memoryStore } from \"../../../cache\";\nimport type {\n FUSportsCompetition,\n FUSportsTeamCompetitor,\n FUSportsPlayerCompetitor,\n FUSportsCountry,\n FUSportsVenue,\n FUSportsCoach,\n FUSportsRelated,\n FUBranding,\n FUSportsCompetitionSummary,\n FUSportsTeamSummary,\n FUSportsPlayerSummary,\n FUSportsCountrySummary,\n FUSportsVenueSummary,\n FUSportsCoachSummary,\n} from \"../../../types/canonical/base.types\";\nimport type { SearchEntityResult, SearchEntitySummary } from \"./types\";\nimport type {\n RawTranslation,\n RawAsset,\n RawRelated,\n RawProviderRef,\n RawBranding,\n RawTeamBranding,\n RawSearchEntityBase,\n RawCompetition,\n RawTeam,\n RawAthlete,\n RawCountry,\n RawVenue,\n RawCoach,\n} from \"./raw-types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve name/shortName in target language.\n * Fallback order: target lang → EN → raw name.\n */\nexport function resolveTranslation(\n translations: RawTranslation[],\n lang: string,\n fallbackName: string,\n fallbackShortName?: string | null\n): { name: string; shortName?: string } {\n const upperLang = lang.toUpperCase();\n\n const target = translations.find((t) => t.language.toUpperCase() === upperLang);\n if (target) {\n return {\n name: target.name,\n shortName: target.short_name ?? fallbackShortName ?? undefined,\n };\n }\n\n // Fallback to EN\n if (upperLang !== \"EN\") {\n const en = translations.find((t) => t.language.toUpperCase() === \"EN\");\n if (en) {\n return {\n name: en.name,\n shortName: en.short_name ?? fallbackShortName ?? undefined,\n };\n }\n }\n\n return {\n name: fallbackName,\n shortName: fallbackShortName ?? undefined,\n };\n}\n\n/**\n * Map [{key: \"LOGO\", value: \"url\"}] → { logo: \"url\" }\n */\nexport function resolveAssets(assets: RawAsset[]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const asset of assets) {\n result[asset.key.toLowerCase()] = asset.value;\n }\n return result;\n}\n\n/**\n * Map raw branding snake_case → canonical FUBranding camelCase.\n */\nexport function resolveBranding(raw: RawBranding | RawTeamBranding | undefined | null): FUBranding | undefined {\n if (!raw) return undefined;\n\n const branding: FUBranding = {};\n if (raw.primary_color) branding.primaryColor = raw.primary_color;\n if (raw.secondary_color) branding.secondaryColor = raw.secondary_color;\n if (raw.text_color) branding.textColor = raw.text_color;\n if (raw.background_color) branding.backgroundColor = raw.background_color;\n if (raw.background_gradient_from_color) branding.backgroundGradientFromColor = raw.background_gradient_from_color;\n if (raw.background_gradient_to_color) branding.backgroundGradientToColor = raw.background_gradient_to_color;\n if (raw.background_image) branding.backgroundImage = raw.background_image;\n\n return Object.keys(branding).length > 0 ? branding : undefined;\n}\n\n/** Map raw provider_ref → canonical providerRef */\nexport function resolveProviderRef(refs: RawProviderRef[]): { provider: string; id: string }[] {\n return refs.map((r) => ({ provider: r.provider, id: r.id }));\n}\n\n/** Extract related IDs by relationship type */\nexport function getRelatedIds(related: RawRelated[], relationship: string): string[] {\n return related.filter((r) => r.relationship === relationship).map((r) => r.related_id);\n}\n\n/**\n * Resolve a country from cache (one level deep).\n * Returns FUSportsCountry with name in target lang if cached, or { id } if not.\n */\nexport function resolveCountry(\n countryId: string | null | undefined,\n related: RawRelated[],\n lang: string\n): FUSportsCountry | undefined {\n // Determine the country ID — from direct field or related array\n const id = countryId || getRelatedIds(related, \"COUNTRY\")[0];\n if (!id) return undefined;\n\n // Try cache lookup\n const cachedEntry = memoryStore.get<RawCountry>(id) ?? memoryStore.get<RawCountry>(`entity:${id}`);\n\n if (cachedEntry?.data) {\n const raw = cachedEntry.data;\n return transformCountrySummary(raw, lang);\n }\n\n // Not in cache — return partial\n return { id, name: id };\n}\n\n// ---------------------------------------------------------------------------\n// Summary transforms — used for list/search views AND one-level-deep related\n// entity hydration. These do NOT populate `related` or `providerRef`.\n// ---------------------------------------------------------------------------\n\nexport function transformCountrySummary(raw: RawCountry, lang: string): FUSportsCountrySummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n\n return {\n id: raw.id,\n name,\n ...(raw.country_code ? { code: raw.country_code } : {}),\n ...(assets.flag ? { flag: assets.flag } : {}),\n ...(shortName ? { shortName } : {}),\n };\n}\n\nexport function transformCompetitionSummary(raw: RawCompetition, lang: string): FUSportsCompetitionSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.branding);\n const country = resolveCountry(null, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.format ? { type: raw.format as FUSportsCompetition[\"type\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformTeamSummary(raw: RawTeam, lang: string): FUSportsTeamSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.three_letter_code ? { threeLetterCode: raw.three_letter_code } : {}),\n ...(raw.full_name ? { fullName: raw.full_name } : {}),\n ...(raw.nickname ? { nickname: raw.nickname } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsTeamCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformAthleteSummary(raw: RawAthlete, lang: string): FUSportsPlayerSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n type: \"player\",\n ...(shortName ? { shortName } : {}),\n ...(raw.position ? { position: raw.position } : {}),\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(raw.shirt_number != null ? { shirtNumber: raw.shirt_number } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsPlayerCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo || assets.headshot\n ? { assets: { ...(assets.logo ? { logo: assets.logo } : {}), ...(assets.headshot ? { photo: assets.headshot } : {}) } }\n : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformVenueSummary(raw: RawVenue, lang: string): FUSportsVenueSummary {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n const hasProfile = raw.capacity != null || raw.latitude != null || raw.longitude != null;\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(country ? { country } : {}),\n ...(hasProfile\n ? {\n profile: {\n ...(raw.capacity != null ? { capacity: raw.capacity } : {}),\n ...(raw.latitude != null ? { latitude: raw.latitude } : {}),\n ...(raw.longitude != null ? { longitude: raw.longitude } : {}),\n },\n }\n : {}),\n };\n}\n\nexport function transformCoachSummary(raw: RawCoach, lang: string): FUSportsCoachSummary {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(country ? { country } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Related entity resolution (one level deep from cache)\n// ---------------------------------------------------------------------------\n\n/**\n * Look up a cached raw entity and determine its type for shallow transformation.\n */\nfunction hydrateRelatedEntity(\n id: string,\n relationship: string,\n lang: string\n): FUSportsCompetition | FUSportsTeamCompetitor | FUSportsPlayerCompetitor | FUSportsCountry | undefined {\n const entry = memoryStore.get<RawSearchEntityBase & Record<string, unknown>>(id)\n ?? memoryStore.get<RawSearchEntityBase & Record<string, unknown>>(`entity:${id}`);\n\n if (!entry?.data) return undefined;\n\n const raw = entry.data;\n switch (relationship) {\n case \"COMPETITION\":\n return transformCompetitionSummary(raw as unknown as RawCompetition, lang);\n case \"TEAM\":\n return transformTeamSummary(raw as unknown as RawTeam, lang);\n case \"ATHLETE\":\n return transformAthleteSummary(raw as unknown as RawAthlete, lang);\n case \"COUNTRY\":\n return transformCountrySummary(raw as unknown as RawCountry, lang);\n default:\n return undefined;\n }\n}\n\n/**\n * Resolve all related entries from cache, grouped by relationship type.\n * Returns undefined if there are no related entries.\n */\nexport function resolveRelated(related: RawRelated[], lang: string): FUSportsRelated | undefined {\n if (!related || related.length === 0) return undefined;\n\n const result: FUSportsRelated = {};\n\n for (const entry of related) {\n const hydrated = hydrateRelatedEntity(entry.related_id, entry.relationship, lang);\n // Skip entries not in cache — the prefetch step in index.ts should have\n // fetched them. If still missing, the entity was not found by the API.\n if (!hydrated) continue;\n\n switch (entry.relationship) {\n case \"COMPETITION\":\n (result.competitions ??= []).push(hydrated as FUSportsCompetition);\n break;\n case \"TEAM\":\n (result.teams ??= []).push(hydrated as FUSportsTeamCompetitor);\n break;\n case \"ATHLETE\":\n (result.athletes ??= []).push(hydrated as FUSportsPlayerCompetitor);\n break;\n case \"COUNTRY\":\n (result.countries ??= []).push(hydrated as FUSportsCountry);\n break;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Entity transformers\n// ---------------------------------------------------------------------------\n\nexport function transformCompetition(raw: RawCompetition, lang: string): FUSportsCompetition {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.branding);\n const country = resolveCountry(null, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.format ? { type: raw.format as FUSportsCompetition[\"type\"] } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsCompetition[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformTeam(raw: RawTeam, lang: string): FUSportsTeamCompetitor {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.three_letter_code ? { threeLetterCode: raw.three_letter_code } : {}),\n ...(raw.full_name ? { fullName: raw.full_name } : {}),\n ...(raw.nickname ? { nickname: raw.nickname } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsTeamCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformAthlete(raw: RawAthlete, lang: string): FUSportsPlayerCompetitor {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n type: \"player\",\n ...(shortName ? { shortName } : {}),\n ...(raw.position ? { position: raw.position } : {}),\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(raw.shirt_number != null ? { shirtNumber: raw.shirt_number } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsPlayerCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo || assets.headshot\n ? { assets: { ...(assets.logo ? { logo: assets.logo } : {}), ...(assets.headshot ? { photo: assets.headshot } : {}) } }\n : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformCountry(raw: RawCountry, lang: string): FUSportsCountry {\n const summary = transformCountrySummary(raw, lang);\n return {\n ...summary,\n sport: raw.sport,\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n };\n}\n\nexport function transformVenue(raw: RawVenue, lang: string): FUSportsVenue {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n const hasProfile = raw.capacity != null || raw.latitude != null || raw.longitude != null;\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(country ? { country } : {}),\n ...(hasProfile\n ? {\n profile: {\n ...(raw.capacity != null ? { capacity: raw.capacity } : {}),\n ...(raw.latitude != null ? { latitude: raw.latitude } : {}),\n ...(raw.longitude != null ? { longitude: raw.longitude } : {}),\n },\n }\n : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformCoach(raw: RawCoach, lang: string): FUSportsCoach {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(country ? { country } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Main dispatcher\n// ---------------------------------------------------------------------------\n\n/**\n * Determine entity type from raw data and call the appropriate transformer.\n * The raw API uses `content_type` for competitions and `type` / general context for others.\n */\nexport function transformEntity(raw: RawSearchEntityBase & Record<string, unknown>, lang: string): SearchEntityResult {\n // Determine entity type from raw fields\n const contentType = (raw.content_type as string)?.toUpperCase?.();\n const type = (raw.type as string)?.toUpperCase?.();\n const entityType = (raw.entityType as string)?.toLowerCase?.();\n\n if (contentType === \"COMPETITION\" || entityType === \"competition\") {\n return { ...transformCompetition(raw as unknown as RawCompetition, lang), entityType: \"competition\" };\n }\n\n if (entityType === \"country\" || raw.country_code !== undefined) {\n return { ...transformCountry(raw as RawCountry, lang), entityType: \"country\" };\n }\n\n if (entityType === \"venue\" || (raw.capacity !== undefined && !entityType)) {\n return { ...transformVenue(raw as RawVenue, lang), entityType: \"venue\" };\n }\n\n if (entityType === \"coach\" || (type === \"COACH\")) {\n return { ...transformCoach(raw as RawCoach, lang), entityType: \"coach\" };\n }\n\n if (entityType === \"athlete\" || type === \"PLAYER\" || raw.position !== undefined || raw.shirt_number !== undefined) {\n return { ...transformAthlete(raw as RawAthlete, lang), entityType: \"athlete\" };\n }\n\n // Default to team\n if (entityType === \"team\" || type === \"TEAM\" || raw.three_letter_code !== undefined) {\n return { ...transformTeam(raw as RawTeam, lang), entityType: \"team\" };\n }\n\n // Fallback: treat as team (most common entity type)\n return { ...transformTeam(raw as RawTeam, lang), entityType: \"team\" };\n}\n\n/**\n * Summary dispatcher — like transformEntity but calls summary transforms.\n * Returns lightweight types without `related` or `providerRef`.\n */\nexport function transformEntitySummary(raw: RawSearchEntityBase & Record<string, unknown>, lang: string): SearchEntitySummary {\n const contentType = (raw.content_type as string)?.toUpperCase?.();\n const type = (raw.type as string)?.toUpperCase?.();\n const entityType = (raw.entityType as string)?.toLowerCase?.();\n\n if (contentType === \"COMPETITION\" || entityType === \"competition\") {\n return { ...transformCompetitionSummary(raw as unknown as RawCompetition, lang), entityType: \"competition\" };\n }\n\n if (entityType === \"country\" || raw.country_code !== undefined) {\n return { ...transformCountrySummary(raw as RawCountry, lang), entityType: \"country\" };\n }\n\n if (entityType === \"venue\" || (raw.capacity !== undefined && !entityType)) {\n return { ...transformVenueSummary(raw as RawVenue, lang), entityType: \"venue\" };\n }\n\n if (entityType === \"coach\" || (type === \"COACH\")) {\n return { ...transformCoachSummary(raw as RawCoach, lang), entityType: \"coach\" };\n }\n\n if (entityType === \"athlete\" || type === \"PLAYER\" || raw.position !== undefined || raw.shirt_number !== undefined) {\n return { ...transformAthleteSummary(raw as RawAthlete, lang), entityType: \"athlete\" };\n }\n\n if (entityType === \"team\" || type === \"TEAM\" || raw.three_letter_code !== undefined) {\n return { ...transformTeamSummary(raw as RawTeam, lang), entityType: \"team\" };\n }\n\n return { ...transformTeamSummary(raw as RawTeam, lang), entityType: \"team\" };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transformer.js","sources":["../../../../src/lib/api/fansunited/search/transformer.ts"],"sourcesContent":["/**\n * Raw → Canonical transformer for Search API entities.\n *\n * Resolves translations to a target language (with EN fallback),\n * maps raw snake_case fields to canonical camelCase types,\n * and hydrates related entries (country + related) one level deep from cache.\n */\n\nimport { memoryStore, CACHE_KEY_PREFIX } from \"../../../cache\";\nimport type {\n FUSportsCompetition,\n FUSportsTeamCompetitor,\n FUSportsPlayerCompetitor,\n FUSportsCountry,\n FUSportsVenue,\n FUSportsCoach,\n FUSportsRelated,\n FUBranding,\n FUSportsCompetitionSummary,\n FUSportsTeamSummary,\n FUSportsPlayerSummary,\n FUSportsCountrySummary,\n FUSportsVenueSummary,\n FUSportsCoachSummary,\n} from \"../../../types/canonical/base.types\";\nimport type { SearchEntityResult, SearchEntitySummary } from \"./types\";\nimport type {\n RawTranslation,\n RawAsset,\n RawRelated,\n RawProviderRef,\n RawBranding,\n RawTeamBranding,\n RawSearchEntityBase,\n RawCompetition,\n RawTeam,\n RawAthlete,\n RawCountry,\n RawVenue,\n RawCoach,\n} from \"./raw-types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve name/shortName in target language.\n * Fallback order: target lang → EN → raw name.\n */\nexport function resolveTranslation(\n translations: RawTranslation[],\n lang: string,\n fallbackName: string,\n fallbackShortName?: string | null\n): { name: string; shortName?: string } {\n const upperLang = lang.toUpperCase();\n\n const target = translations.find((t) => t.language.toUpperCase() === upperLang);\n if (target) {\n return {\n name: target.name,\n shortName: target.short_name ?? fallbackShortName ?? undefined,\n };\n }\n\n // Fallback to EN\n if (upperLang !== \"EN\") {\n const en = translations.find((t) => t.language.toUpperCase() === \"EN\");\n if (en) {\n return {\n name: en.name,\n shortName: en.short_name ?? fallbackShortName ?? undefined,\n };\n }\n }\n\n return {\n name: fallbackName,\n shortName: fallbackShortName ?? undefined,\n };\n}\n\n/**\n * Map [{key: \"LOGO\", value: \"url\"}] → { logo: \"url\" }\n */\nexport function resolveAssets(assets: RawAsset[]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const asset of assets) {\n result[asset.key.toLowerCase()] = asset.value;\n }\n return result;\n}\n\n/**\n * Map raw branding snake_case → canonical FUBranding camelCase.\n */\nexport function resolveBranding(raw: RawBranding | RawTeamBranding | undefined | null): FUBranding | undefined {\n if (!raw) return undefined;\n\n const branding: FUBranding = {};\n if (raw.primary_color) branding.primaryColor = raw.primary_color;\n if (raw.secondary_color) branding.secondaryColor = raw.secondary_color;\n if (raw.text_color) branding.textColor = raw.text_color;\n if (raw.background_color) branding.backgroundColor = raw.background_color;\n if (raw.background_gradient_from_color) branding.backgroundGradientFromColor = raw.background_gradient_from_color;\n if (raw.background_gradient_to_color) branding.backgroundGradientToColor = raw.background_gradient_to_color;\n if (raw.background_image) branding.backgroundImage = raw.background_image;\n\n return Object.keys(branding).length > 0 ? branding : undefined;\n}\n\n/** Map raw provider_ref → canonical providerRef */\nexport function resolveProviderRef(refs: RawProviderRef[]): { provider: string; id: string }[] {\n return refs.map((r) => ({ provider: r.provider, id: r.id }));\n}\n\n/** Extract related IDs by relationship type */\nexport function getRelatedIds(related: RawRelated[], relationship: string): string[] {\n return related.filter((r) => r.relationship === relationship).map((r) => r.related_id);\n}\n\n/**\n * Resolve a country from cache (one level deep).\n * Returns FUSportsCountry with name in target lang if cached, or { id } if not.\n */\nexport function resolveCountry(\n countryId: string | null | undefined,\n related: RawRelated[],\n lang: string\n): FUSportsCountry | undefined {\n // Determine the country ID — from direct field or related array\n const id = countryId || getRelatedIds(related, \"COUNTRY\")[0];\n if (!id) return undefined;\n\n // Try cache lookup\n const cachedEntry = memoryStore.get<RawCountry>(id) ?? memoryStore.get<RawCountry>(`${CACHE_KEY_PREFIX}entity:${id}`);\n\n if (cachedEntry?.data) {\n const raw = cachedEntry.data;\n return transformCountrySummary(raw, lang);\n }\n\n // Not in cache — return partial\n return { id, name: id };\n}\n\n// ---------------------------------------------------------------------------\n// Summary transforms — used for list/search views AND one-level-deep related\n// entity hydration. These do NOT populate `related` or `providerRef`.\n// ---------------------------------------------------------------------------\n\nexport function transformCountrySummary(raw: RawCountry, lang: string): FUSportsCountrySummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n\n return {\n id: raw.id,\n name,\n ...(raw.country_code ? { code: raw.country_code } : {}),\n ...(assets.flag ? { flag: assets.flag } : {}),\n ...(shortName ? { shortName } : {}),\n };\n}\n\nexport function transformCompetitionSummary(raw: RawCompetition, lang: string): FUSportsCompetitionSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.branding);\n const country = resolveCountry(null, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.format ? { type: raw.format as FUSportsCompetition[\"type\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformTeamSummary(raw: RawTeam, lang: string): FUSportsTeamSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.three_letter_code ? { threeLetterCode: raw.three_letter_code } : {}),\n ...(raw.full_name ? { fullName: raw.full_name } : {}),\n ...(raw.nickname ? { nickname: raw.nickname } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsTeamCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformAthleteSummary(raw: RawAthlete, lang: string): FUSportsPlayerSummary {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n type: \"player\",\n ...(shortName ? { shortName } : {}),\n ...(raw.position ? { position: raw.position } : {}),\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(raw.shirt_number != null ? { shirtNumber: raw.shirt_number } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsPlayerCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo || assets.headshot\n ? { assets: { ...(assets.logo ? { logo: assets.logo } : {}), ...(assets.headshot ? { photo: assets.headshot } : {}) } }\n : {}),\n ...(branding ? { metadata: { branding } } : {}),\n };\n}\n\nexport function transformVenueSummary(raw: RawVenue, lang: string): FUSportsVenueSummary {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n const hasProfile = raw.capacity != null || raw.latitude != null || raw.longitude != null;\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(country ? { country } : {}),\n ...(hasProfile\n ? {\n profile: {\n ...(raw.capacity != null ? { capacity: raw.capacity } : {}),\n ...(raw.latitude != null ? { latitude: raw.latitude } : {}),\n ...(raw.longitude != null ? { longitude: raw.longitude } : {}),\n },\n }\n : {}),\n };\n}\n\nexport function transformCoachSummary(raw: RawCoach, lang: string): FUSportsCoachSummary {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(country ? { country } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Related entity resolution (one level deep from cache)\n// ---------------------------------------------------------------------------\n\n/**\n * Look up a cached raw entity and determine its type for shallow transformation.\n */\nfunction hydrateRelatedEntity(\n id: string,\n relationship: string,\n lang: string\n): FUSportsCompetition | FUSportsTeamCompetitor | FUSportsPlayerCompetitor | FUSportsCountry | undefined {\n const entry = memoryStore.get<RawSearchEntityBase & Record<string, unknown>>(id)\n ?? memoryStore.get<RawSearchEntityBase & Record<string, unknown>>(`${CACHE_KEY_PREFIX}entity:${id}`);\n\n if (!entry?.data) return undefined;\n\n const raw = entry.data;\n switch (relationship) {\n case \"COMPETITION\":\n return transformCompetitionSummary(raw as unknown as RawCompetition, lang);\n case \"TEAM\":\n return transformTeamSummary(raw as unknown as RawTeam, lang);\n case \"ATHLETE\":\n return transformAthleteSummary(raw as unknown as RawAthlete, lang);\n case \"COUNTRY\":\n return transformCountrySummary(raw as unknown as RawCountry, lang);\n default:\n return undefined;\n }\n}\n\n/**\n * Resolve all related entries from cache, grouped by relationship type.\n * Returns undefined if there are no related entries.\n */\nexport function resolveRelated(related: RawRelated[], lang: string): FUSportsRelated | undefined {\n if (!related || related.length === 0) return undefined;\n\n const result: FUSportsRelated = {};\n\n for (const entry of related) {\n const hydrated = hydrateRelatedEntity(entry.related_id, entry.relationship, lang);\n // Skip entries not in cache — the prefetch step in index.ts should have\n // fetched them. If still missing, the entity was not found by the API.\n if (!hydrated) continue;\n\n switch (entry.relationship) {\n case \"COMPETITION\":\n (result.competitions ??= []).push(hydrated as FUSportsCompetition);\n break;\n case \"TEAM\":\n (result.teams ??= []).push(hydrated as FUSportsTeamCompetitor);\n break;\n case \"ATHLETE\":\n (result.athletes ??= []).push(hydrated as FUSportsPlayerCompetitor);\n break;\n case \"COUNTRY\":\n (result.countries ??= []).push(hydrated as FUSportsCountry);\n break;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Entity transformers\n// ---------------------------------------------------------------------------\n\nexport function transformCompetition(raw: RawCompetition, lang: string): FUSportsCompetition {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.branding);\n const country = resolveCountry(null, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.format ? { type: raw.format as FUSportsCompetition[\"type\"] } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsCompetition[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformTeam(raw: RawTeam, lang: string): FUSportsTeamCompetitor {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(shortName ? { shortName } : {}),\n ...(raw.three_letter_code ? { threeLetterCode: raw.three_letter_code } : {}),\n ...(raw.full_name ? { fullName: raw.full_name } : {}),\n ...(raw.nickname ? { nickname: raw.nickname } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsTeamCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo ? { assets: { logo: assets.logo } } : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformAthlete(raw: RawAthlete, lang: string): FUSportsPlayerCompetitor {\n const { name, shortName } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const assets = resolveAssets(raw.assets ?? []);\n const branding = resolveBranding(raw.metadata?.branding);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n type: \"player\",\n ...(shortName ? { shortName } : {}),\n ...(raw.position ? { position: raw.position } : {}),\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(raw.shirt_number != null ? { shirtNumber: raw.shirt_number } : {}),\n ...(raw.gender ? { gender: raw.gender as FUSportsPlayerCompetitor[\"gender\"] } : {}),\n ...(country ? { country } : {}),\n ...(assets.logo || assets.headshot\n ? { assets: { ...(assets.logo ? { logo: assets.logo } : {}), ...(assets.headshot ? { photo: assets.headshot } : {}) } }\n : {}),\n ...(branding ? { metadata: { branding } } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformCountry(raw: RawCountry, lang: string): FUSportsCountry {\n const summary = transformCountrySummary(raw, lang);\n return {\n ...summary,\n sport: raw.sport,\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n };\n}\n\nexport function transformVenue(raw: RawVenue, lang: string): FUSportsVenue {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n const hasProfile = raw.capacity != null || raw.latitude != null || raw.longitude != null;\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(country ? { country } : {}),\n ...(hasProfile\n ? {\n profile: {\n ...(raw.capacity != null ? { capacity: raw.capacity } : {}),\n ...(raw.latitude != null ? { latitude: raw.latitude } : {}),\n ...(raw.longitude != null ? { longitude: raw.longitude } : {}),\n },\n }\n : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\nexport function transformCoach(raw: RawCoach, lang: string): FUSportsCoach {\n const { name } = resolveTranslation(raw.translations ?? [], lang, raw.name, raw.short_name);\n const country = resolveCountry(raw.country_id, raw.related ?? [], lang);\n const related = resolveRelated(raw.related ?? [], lang);\n\n return {\n id: raw.id,\n name,\n sport: raw.sport,\n ...(raw.birth_date ? { birthdate: raw.birth_date } : {}),\n ...(country ? { country } : {}),\n ...(raw.provider_ref?.length ? { providerRef: resolveProviderRef(raw.provider_ref) } : {}),\n ...(related ? { related } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Main dispatcher\n// ---------------------------------------------------------------------------\n\n/**\n * Determine entity type from raw data and call the appropriate transformer.\n * The raw API uses `content_type` for competitions and `type` / general context for others.\n */\nexport function transformEntity(raw: RawSearchEntityBase & Record<string, unknown>, lang: string): SearchEntityResult {\n // Determine entity type from raw fields\n const contentType = (raw.content_type as string)?.toUpperCase?.();\n const type = (raw.type as string)?.toUpperCase?.();\n const entityType = (raw.entityType as string)?.toLowerCase?.();\n\n if (contentType === \"COMPETITION\" || entityType === \"competition\") {\n return { ...transformCompetition(raw as unknown as RawCompetition, lang), entityType: \"competition\" };\n }\n\n if (entityType === \"country\" || raw.country_code !== undefined) {\n return { ...transformCountry(raw as RawCountry, lang), entityType: \"country\" };\n }\n\n if (entityType === \"venue\" || (raw.capacity !== undefined && !entityType)) {\n return { ...transformVenue(raw as RawVenue, lang), entityType: \"venue\" };\n }\n\n if (entityType === \"coach\" || (type === \"COACH\")) {\n return { ...transformCoach(raw as RawCoach, lang), entityType: \"coach\" };\n }\n\n if (entityType === \"athlete\" || type === \"PLAYER\" || raw.position !== undefined || raw.shirt_number !== undefined) {\n return { ...transformAthlete(raw as RawAthlete, lang), entityType: \"athlete\" };\n }\n\n // Default to team\n if (entityType === \"team\" || type === \"TEAM\" || raw.three_letter_code !== undefined) {\n return { ...transformTeam(raw as RawTeam, lang), entityType: \"team\" };\n }\n\n // Fallback: treat as team (most common entity type)\n return { ...transformTeam(raw as RawTeam, lang), entityType: \"team\" };\n}\n\n/**\n * Summary dispatcher — like transformEntity but calls summary transforms.\n * Returns lightweight types without `related` or `providerRef`.\n */\nexport function transformEntitySummary(raw: RawSearchEntityBase & Record<string, unknown>, lang: string): SearchEntitySummary {\n const contentType = (raw.content_type as string)?.toUpperCase?.();\n const type = (raw.type as string)?.toUpperCase?.();\n const entityType = (raw.entityType as string)?.toLowerCase?.();\n\n if (contentType === \"COMPETITION\" || entityType === \"competition\") {\n return { ...transformCompetitionSummary(raw as unknown as RawCompetition, lang), entityType: \"competition\" };\n }\n\n if (entityType === \"country\" || raw.country_code !== undefined) {\n return { ...transformCountrySummary(raw as RawCountry, lang), entityType: \"country\" };\n }\n\n if (entityType === \"venue\" || (raw.capacity !== undefined && !entityType)) {\n return { ...transformVenueSummary(raw as RawVenue, lang), entityType: \"venue\" };\n }\n\n if (entityType === \"coach\" || (type === \"COACH\")) {\n return { ...transformCoachSummary(raw as RawCoach, lang), entityType: \"coach\" };\n }\n\n if (entityType === \"athlete\" || type === \"PLAYER\" || raw.position !== undefined || raw.shirt_number !== undefined) {\n return { ...transformAthleteSummary(raw as RawAthlete, lang), entityType: \"athlete\" };\n }\n\n if (entityType === \"team\" || type === \"TEAM\" || raw.three_letter_code !== undefined) {\n return { ...transformTeamSummary(raw as RawTeam, lang), entityType: \"team\" };\n }\n\n return { ...transformTeamSummary(raw as RawTeam, lang), entityType: \"team\" };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=exports.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exports.test.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/api/fansunited/sports/competition/__tests__/exports.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hydrated.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydrated.test.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/api/fansunited/sports/competition/__tests__/hydrated.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/api/fansunited/sports/competition/__tests__/index.test.ts"],"names":[],"mappings":""}