fansunited-data-layer 0.13.0 → 0.14.2

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 (242) hide show
  1. package/api/fansunited/constants.js +5 -0
  2. package/api/fansunited/constants.js.map +1 -0
  3. package/api/fansunited/football/competition/index.js +21 -0
  4. package/api/fansunited/football/competition/index.js.map +1 -0
  5. package/api/fansunited/football/competition/transformer.js +41 -0
  6. package/api/fansunited/football/competition/transformer.js.map +1 -0
  7. package/api/fansunited/football/competitions/index.js +56 -0
  8. package/api/fansunited/football/competitions/index.js.map +1 -0
  9. package/api/fansunited/football/competitions/transformer.js +68 -0
  10. package/api/fansunited/football/competitions/transformer.js.map +1 -0
  11. package/api/fansunited/football/http.js +7 -0
  12. package/api/fansunited/football/http.js.map +1 -0
  13. package/api/fansunited/football/matches/index.js +132 -0
  14. package/api/fansunited/football/matches/index.js.map +1 -0
  15. package/api/fansunited/football/matches/transformer.js +148 -0
  16. package/api/fansunited/football/matches/transformer.js.map +1 -0
  17. package/api/fansunited/football/players/index.js +60 -0
  18. package/api/fansunited/football/players/index.js.map +1 -0
  19. package/api/fansunited/football/players/transformer.js +85 -0
  20. package/api/fansunited/football/players/transformer.js.map +1 -0
  21. package/api/fansunited/football/search/index.js +64 -0
  22. package/api/fansunited/football/search/index.js.map +1 -0
  23. package/api/fansunited/football/search/transformer.js +114 -0
  24. package/api/fansunited/football/search/transformer.js.map +1 -0
  25. package/api/fansunited/football/teams/index.js +66 -0
  26. package/api/fansunited/football/teams/index.js.map +1 -0
  27. package/api/fansunited/football/teams/transformer.js +53 -0
  28. package/api/fansunited/football/teams/transformer.js.map +1 -0
  29. package/api/fansunited/http.d.ts.map +1 -1
  30. package/api/fansunited/http.js +70 -0
  31. package/api/fansunited/http.js.map +1 -0
  32. package/api/fansunited/search/constants.js +5 -0
  33. package/api/fansunited/search/constants.js.map +1 -0
  34. package/api/fansunited/search/http.js +7 -0
  35. package/api/fansunited/search/http.js.map +1 -0
  36. package/api/fansunited/search/index.js +308 -0
  37. package/api/fansunited/search/index.js.map +1 -0
  38. package/api/fansunited/search/transformer.js +374 -0
  39. package/api/fansunited/search/transformer.js.map +1 -0
  40. package/api/fansunited-sdk/loyalty/matches.js +21 -0
  41. package/api/fansunited-sdk/loyalty/matches.js.map +1 -0
  42. package/api/fansunited-sdk/loyalty/template.js +52 -0
  43. package/api/fansunited-sdk/loyalty/template.js.map +1 -0
  44. package/api/fansunited-sdk/odds/matches.js +109 -0
  45. package/api/fansunited-sdk/odds/matches.js.map +1 -0
  46. package/api/sportal365-sports/basketball/games/index.js +32 -0
  47. package/api/sportal365-sports/basketball/games/index.js.map +1 -0
  48. package/api/sportal365-sports/basketball/games/transformers/game.js +137 -0
  49. package/api/sportal365-sports/basketball/games/transformers/game.js.map +1 -0
  50. package/api/sportal365-sports/basketball/http.js +7 -0
  51. package/api/sportal365-sports/basketball/http.js.map +1 -0
  52. package/api/sportal365-sports/constants.js +15 -0
  53. package/api/sportal365-sports/constants.js.map +1 -0
  54. package/api/sportal365-sports/football/competitions/index.js +52 -0
  55. package/api/sportal365-sports/football/competitions/index.js.map +1 -0
  56. package/api/sportal365-sports/football/competitions/utils.js +92 -0
  57. package/api/sportal365-sports/football/competitions/utils.js.map +1 -0
  58. package/api/sportal365-sports/football/http.js +7 -0
  59. package/api/sportal365-sports/football/http.js.map +1 -0
  60. package/api/sportal365-sports/football/matches/index.js +206 -0
  61. package/api/sportal365-sports/football/matches/index.js.map +1 -0
  62. package/api/sportal365-sports/football/matches/transformers/commentary.js +27 -0
  63. package/api/sportal365-sports/football/matches/transformers/commentary.js.map +1 -0
  64. package/api/sportal365-sports/football/matches/transformers/lineup.js +74 -0
  65. package/api/sportal365-sports/football/matches/transformers/lineup.js.map +1 -0
  66. package/api/sportal365-sports/football/matches/transformers/match-event.js +60 -0
  67. package/api/sportal365-sports/football/matches/transformers/match-event.js.map +1 -0
  68. package/api/sportal365-sports/football/matches/transformers/match.js +195 -0
  69. package/api/sportal365-sports/football/matches/transformers/match.js.map +1 -0
  70. package/api/sportal365-sports/football/matches/transformers/odds.js +11 -0
  71. package/api/sportal365-sports/football/matches/transformers/odds.js.map +1 -0
  72. package/api/sportal365-sports/football/matches/transformers/statistics.js +41 -0
  73. package/api/sportal365-sports/football/matches/transformers/statistics.js.map +1 -0
  74. package/api/sportal365-sports/football/search/index.js +42 -0
  75. package/api/sportal365-sports/football/search/index.js.map +1 -0
  76. package/api/sportal365-sports/football/search/search.transformer.js +166 -0
  77. package/api/sportal365-sports/football/search/search.transformer.js.map +1 -0
  78. package/api/sportal365-sports/football/standings/index.js +28 -0
  79. package/api/sportal365-sports/football/standings/index.js.map +1 -0
  80. package/api/sportal365-sports/football/standings/standing.transformer.js +107 -0
  81. package/api/sportal365-sports/football/standings/standing.transformer.js.map +1 -0
  82. package/api/sportal365-sports/football/statistics/index.js +154 -0
  83. package/api/sportal365-sports/football/statistics/index.js.map +1 -0
  84. package/api/sportal365-sports/football/statistics/player-career.transformer.js +77 -0
  85. package/api/sportal365-sports/football/statistics/player-career.transformer.js.map +1 -0
  86. package/api/sportal365-sports/football/statistics/player-recent.transformer.js +54 -0
  87. package/api/sportal365-sports/football/statistics/player-recent.transformer.js.map +1 -0
  88. package/api/sportal365-sports/football/statistics/player-season.transformer.js +147 -0
  89. package/api/sportal365-sports/football/statistics/player-season.transformer.js.map +1 -0
  90. package/api/sportal365-sports/football/teams/index.js +73 -0
  91. package/api/sportal365-sports/football/teams/index.js.map +1 -0
  92. package/api/sportal365-sports/football/teams/utils.js +196 -0
  93. package/api/sportal365-sports/football/teams/utils.js.map +1 -0
  94. package/api/sportal365-sports/http.js +58 -0
  95. package/api/sportal365-sports/http.js.map +1 -0
  96. package/api/sportal365-sports/search/http.js +7 -0
  97. package/api/sportal365-sports/search/http.js.map +1 -0
  98. package/api/sportal365-sports/search/index.js +61 -0
  99. package/api/sportal365-sports/search/index.js.map +1 -0
  100. package/api/sportal365-sports/search/search.transformer.js +254 -0
  101. package/api/sportal365-sports/search/search.transformer.js.map +1 -0
  102. package/api/sportal365-sports/shared/odds.transformer.js +65 -0
  103. package/api/sportal365-sports/shared/odds.transformer.js.map +1 -0
  104. package/api/sportal365-sports/shared/providerRef.helper.js +31 -0
  105. package/api/sportal365-sports/shared/providerRef.helper.js.map +1 -0
  106. package/api/sportal365-sports/standings/http.js +7 -0
  107. package/api/sportal365-sports/standings/http.js.map +1 -0
  108. package/api/sportal365-sports/standings/index.js +29 -0
  109. package/api/sportal365-sports/standings/index.js.map +1 -0
  110. package/api/sportal365-sports/standings/standing.transformer.js +185 -0
  111. package/api/sportal365-sports/standings/standing.transformer.js.map +1 -0
  112. package/api/sportal365-sports/statistics/http.js +7 -0
  113. package/api/sportal365-sports/statistics/http.js.map +1 -0
  114. package/api/sportal365-sports/statistics/index.js +25 -0
  115. package/api/sportal365-sports/statistics/index.js.map +1 -0
  116. package/api/sportal365-sports/statistics/team-stats.transformer.js +16 -0
  117. package/api/sportal365-sports/statistics/team-stats.transformer.js.map +1 -0
  118. package/api/sportal365-sports/tennis/http.js +7 -0
  119. package/api/sportal365-sports/tennis/http.js.map +1 -0
  120. package/api/sportal365-sports/tennis/matches/index.js +34 -0
  121. package/api/sportal365-sports/tennis/matches/index.js.map +1 -0
  122. package/api/sportal365-sports/tennis/matches/transformers/match.js +193 -0
  123. package/api/sportal365-sports/tennis/matches/transformers/match.js.map +1 -0
  124. package/cache/cache-manager.js +136 -0
  125. package/cache/cache-manager.js.map +1 -0
  126. package/cache/memory-store.js +29 -0
  127. package/cache/memory-store.js.map +1 -0
  128. package/client.js +38 -12337
  129. package/client.js.map +1 -0
  130. package/config/index.js +20 -0
  131. package/config/index.js.map +1 -0
  132. package/fansunited-data-layer.js +146 -3553
  133. package/fansunited-data-layer.js.map +1 -0
  134. package/helpers/competition.helpers.js +11 -0
  135. package/helpers/competition.helpers.js.map +1 -0
  136. package/helpers/player.helpers.js +165 -0
  137. package/helpers/player.helpers.js.map +1 -0
  138. package/helpers/player.hooks.js +34 -0
  139. package/helpers/player.hooks.js.map +1 -0
  140. package/helpers/team.helpers.js +216 -0
  141. package/helpers/team.helpers.js.map +1 -0
  142. package/package.json +6 -8
  143. package/providers/competition/hooks/useCompetitionStats.js +10 -0
  144. package/providers/competition/hooks/useCompetitionStats.js.map +1 -0
  145. package/providers/competition/hooks/useGoalDistribution.js +23 -0
  146. package/providers/competition/hooks/useGoalDistribution.js.map +1 -0
  147. package/providers/competition/hooks/useMatchHelpers.js +85 -0
  148. package/providers/competition/hooks/useMatchHelpers.js.map +1 -0
  149. package/providers/competition/hooks/useStandingsCalculations.js +89 -0
  150. package/providers/competition/hooks/useStandingsCalculations.js.map +1 -0
  151. package/providers/competition/hooks/useStandingsHelpers.js +61 -0
  152. package/providers/competition/hooks/useStandingsHelpers.js.map +1 -0
  153. package/providers/competition/hooks/useTeamPosition.js +15 -0
  154. package/providers/competition/hooks/useTeamPosition.js.map +1 -0
  155. package/providers/competition/hooks/useTeamResultsTable.js +86 -0
  156. package/providers/competition/hooks/useTeamResultsTable.js.map +1 -0
  157. package/providers/competition/utils/competitionStats.js +109 -0
  158. package/providers/competition/utils/competitionStats.js.map +1 -0
  159. package/providers/competition/utils/goalDistribution.js +64 -0
  160. package/providers/competition/utils/goalDistribution.js.map +1 -0
  161. package/providers/competition/utils/standingsCalculations.js +152 -0
  162. package/providers/competition/utils/standingsCalculations.js.map +1 -0
  163. package/providers/competition.context.js +14 -0
  164. package/providers/competition.context.js.map +1 -0
  165. package/providers/competition.provider.js +187 -0
  166. package/providers/competition.provider.js.map +1 -0
  167. package/providers/fansunited-config.context.js +6 -0
  168. package/providers/fansunited-config.context.js.map +1 -0
  169. package/providers/fansunited-config.hooks.js +20 -0
  170. package/providers/fansunited-config.hooks.js.map +1 -0
  171. package/providers/fansunited-config.provider.js +9 -0
  172. package/providers/fansunited-config.provider.js.map +1 -0
  173. package/providers/fansunited-sdk.hook.js +50 -0
  174. package/providers/fansunited-sdk.hook.js.map +1 -0
  175. package/providers/leaderboard/hooks/useMatchHelpers.js +30 -0
  176. package/providers/leaderboard/hooks/useMatchHelpers.js.map +1 -0
  177. package/providers/leaderboard/hooks/useTemplateHelpers.js +39 -0
  178. package/providers/leaderboard/hooks/useTemplateHelpers.js.map +1 -0
  179. package/providers/leaderboard.context.js +14 -0
  180. package/providers/leaderboard.context.js.map +1 -0
  181. package/providers/leaderboard.provider.js +98 -0
  182. package/providers/leaderboard.provider.js.map +1 -0
  183. package/providers/match/hooks/useBatchMatchOdds.js +72 -0
  184. package/providers/match/hooks/useBatchMatchOdds.js.map +1 -0
  185. package/providers/match/hooks/useEventHelpers.js +46 -0
  186. package/providers/match/hooks/useEventHelpers.js.map +1 -0
  187. package/providers/match/hooks/useHeadToHeadHelpers.js +52 -0
  188. package/providers/match/hooks/useHeadToHeadHelpers.js.map +1 -0
  189. package/providers/match/hooks/useLineupHelpers.js +53 -0
  190. package/providers/match/hooks/useLineupHelpers.js.map +1 -0
  191. package/providers/match/hooks/useMatchStandingsCalculations.js +332 -0
  192. package/providers/match/hooks/useMatchStandingsCalculations.js.map +1 -0
  193. package/providers/match/hooks/useMatchStatus.js +37 -0
  194. package/providers/match/hooks/useMatchStatus.js.map +1 -0
  195. package/providers/match/hooks/useOddsHelpers.js +54 -0
  196. package/providers/match/hooks/useOddsHelpers.js.map +1 -0
  197. package/providers/match/hooks/useScoreHelpers.js +34 -0
  198. package/providers/match/hooks/useScoreHelpers.js.map +1 -0
  199. package/providers/match/hooks/useStandingsHelpers.js +53 -0
  200. package/providers/match/hooks/useStandingsHelpers.js.map +1 -0
  201. package/providers/match/hooks/useStatisticsHelpers.js +40 -0
  202. package/providers/match/hooks/useStatisticsHelpers.js.map +1 -0
  203. package/providers/match/hooks/useTeamHelpers.js +38 -0
  204. package/providers/match/hooks/useTeamHelpers.js.map +1 -0
  205. package/providers/match/hooks/useTeamStatsHelpers.js +141 -0
  206. package/providers/match/hooks/useTeamStatsHelpers.js.map +1 -0
  207. package/providers/match.context.js +14 -0
  208. package/providers/match.context.js.map +1 -0
  209. package/providers/match.provider.js +176 -0
  210. package/providers/match.provider.js.map +1 -0
  211. package/providers/team/hooks/useFormStats.js +116 -0
  212. package/providers/team/hooks/useFormStats.js.map +1 -0
  213. package/providers/team/hooks/useMatchHelpers.js +46 -0
  214. package/providers/team/hooks/useMatchHelpers.js.map +1 -0
  215. package/providers/team/hooks/useSquadHelpers.js +67 -0
  216. package/providers/team/hooks/useSquadHelpers.js.map +1 -0
  217. package/providers/team.context.js +14 -0
  218. package/providers/team.context.js.map +1 -0
  219. package/providers/team.provider.js +98 -0
  220. package/providers/team.provider.js.map +1 -0
  221. package/utilities/stats/core/helpers.js +105 -0
  222. package/utilities/stats/core/helpers.js.map +1 -0
  223. package/utilities/stats/core/types.js +5 -0
  224. package/utilities/stats/core/types.js.map +1 -0
  225. package/utilities/stats/match/headToHead.js +83 -0
  226. package/utilities/stats/match/headToHead.js.map +1 -0
  227. package/utilities/stats/match/homeVsAway.js +140 -0
  228. package/utilities/stats/match/homeVsAway.js.map +1 -0
  229. package/utilities/stats/match/overUnder.js +91 -0
  230. package/utilities/stats/match/overUnder.js.map +1 -0
  231. package/utilities/stats/match/result.js +21 -0
  232. package/utilities/stats/match/result.js.map +1 -0
  233. package/utilities/stats/team/commonOpponents.js +77 -0
  234. package/utilities/stats/team/commonOpponents.js.map +1 -0
  235. package/utilities/stats/team/goalStats.js +50 -0
  236. package/utilities/stats/team/goalStats.js.map +1 -0
  237. package/utilities/stats/team/streaks.js +183 -0
  238. package/utilities/stats/team/streaks.js.map +1 -0
  239. package/client.cjs +0 -8
  240. package/fansunited-data-layer.cjs +0 -1
  241. package/matches-BvHU-bP0.js +0 -1795
  242. package/matches-Ci0Ci_Mw.cjs +0 -1
@@ -0,0 +1,308 @@
1
+ import { searchHttp } from "./http.js";
2
+ import { isConfigured, getConfig } from "../../../config/index.js";
3
+ import { transformCompetitionSummary, transformCountrySummary, transformEntity, transformEntitySummary, transformTeamSummary, transformVenueSummary } from "./transformer.js";
4
+ import { cached, cachedBatch } from "../../../cache/cache-manager.js";
5
+ import { memoryStore } from "../../../cache/memory-store.js";
6
+ function hashParams(params) {
7
+ const sorted = Object.entries(params).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${Array.isArray(v) ? v.join(",") : v}`).join("&");
8
+ let hash = 0;
9
+ for (let i = 0; i < sorted.length; i++) {
10
+ hash = (hash << 5) - hash + sorted.charCodeAt(i) | 0;
11
+ }
12
+ return hash.toString(36);
13
+ }
14
+ function cacheIndividualEntities(entities) {
15
+ for (const entity of entities) {
16
+ if (entity.id) {
17
+ memoryStore.set(`entity:${entity.id}`, entity);
18
+ }
19
+ }
20
+ }
21
+ function resolveLanguage(options) {
22
+ if (options?.lang) return options.lang;
23
+ if (isConfigured()) {
24
+ const config = getConfig();
25
+ if (config.fansUnited && "lang" in config.fansUnited && config.fansUnited.lang) {
26
+ return config.fansUnited.lang;
27
+ }
28
+ }
29
+ return "EN";
30
+ }
31
+ function collectMissingIds(entities) {
32
+ const missingIds = /* @__PURE__ */ new Set();
33
+ for (const entity of entities) {
34
+ const raw = entity;
35
+ const related = raw.related;
36
+ if (related) {
37
+ for (const r of related) {
38
+ if (!memoryStore.get(`entity:${r.related_id}`)) {
39
+ missingIds.add(r.related_id);
40
+ }
41
+ }
42
+ }
43
+ const countryId = raw.country_id;
44
+ if (countryId && !memoryStore.get(`entity:${countryId}`)) {
45
+ missingIds.add(countryId);
46
+ }
47
+ }
48
+ return missingIds;
49
+ }
50
+ async function batchFetchAndCache(ids, fetchOptions) {
51
+ 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;
60
+ }
61
+ async function prefetchRelatedEntities(entities, fetchOptions) {
62
+ const pass1Ids = collectMissingIds(entities);
63
+ if (pass1Ids.size === 0) return;
64
+ try {
65
+ const fetched = await batchFetchAndCache(pass1Ids, fetchOptions);
66
+ const pass2Ids = collectMissingIds(fetched);
67
+ if (pass2Ids.size > 0) {
68
+ await batchFetchAndCache(pass2Ids, fetchOptions);
69
+ }
70
+ } catch {
71
+ }
72
+ }
73
+ async function prefetchCountries(entities, fetchOptions) {
74
+ const missingIds = /* @__PURE__ */ new Set();
75
+ for (const entity of entities) {
76
+ const raw = entity;
77
+ const countryId = raw.country_id;
78
+ if (countryId && !memoryStore.get(`entity:${countryId}`)) {
79
+ missingIds.add(countryId);
80
+ }
81
+ const related = raw.related;
82
+ if (related) {
83
+ for (const r of related) {
84
+ if (r.relationship === "COUNTRY" && !memoryStore.get(`entity:${r.related_id}`)) {
85
+ missingIds.add(r.related_id);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ if (missingIds.size === 0) return;
91
+ try {
92
+ await batchFetchAndCache(missingIds, fetchOptions);
93
+ } catch {
94
+ }
95
+ }
96
+ async function getFansUnitedSearchEntities(options = {}, config) {
97
+ const lang = resolveLanguage(options);
98
+ const params = {
99
+ query: options.query,
100
+ content_type: options.contentType,
101
+ ids: options.ids,
102
+ limit: options.limit?.toString(),
103
+ page: options.page?.toString(),
104
+ mode: options.mode,
105
+ sport: options.sport,
106
+ relationship: options.relationship,
107
+ value: options.value
108
+ };
109
+ const cacheKey = `search:entities:${hashParams(params)}`;
110
+ const result = await cached(
111
+ cacheKey,
112
+ "search",
113
+ () => searchHttp.get({
114
+ path: "/v1/entities/search",
115
+ params,
116
+ next: options.next || config?.next,
117
+ config: options.config
118
+ })
119
+ );
120
+ cacheIndividualEntities(result.data);
121
+ await prefetchCountries(result.data, { next: options.next || config?.next, config: options.config });
122
+ const transformed = result.data.map(
123
+ (e) => transformEntitySummary(e, lang)
124
+ );
125
+ return { data: transformed, pagination: result.meta.pagination };
126
+ }
127
+ async function getFansUnitedEntityById(id, options) {
128
+ const lang = resolveLanguage(options);
129
+ const cacheKey = `entity:${id}`;
130
+ const raw = await cached(cacheKey, "search", async () => {
131
+ const response = await searchHttp.get({
132
+ path: "/v1/entities/search",
133
+ params: { ids: [id] },
134
+ next: options?.next,
135
+ config: options?.config
136
+ });
137
+ if (!response.data || response.data.length === 0) {
138
+ throw new Error(`Entity not found: ${id}`);
139
+ }
140
+ return response.data[0];
141
+ });
142
+ await prefetchRelatedEntities([raw], { next: options?.next, config: options?.config });
143
+ return transformEntity(raw, lang);
144
+ }
145
+ async function getFansUnitedEntitiesByIds(ids, options) {
146
+ if (ids.length === 0) return [];
147
+ const lang = resolveLanguage(options);
148
+ const resultsMap = await cachedBatch(
149
+ ids,
150
+ "search",
151
+ async (missingIds) => {
152
+ const response = await searchHttp.get({
153
+ path: "/v1/entities/search",
154
+ params: { ids: missingIds },
155
+ next: options?.next,
156
+ config: options?.config
157
+ });
158
+ const map = /* @__PURE__ */ new Map();
159
+ for (const entity of response.data) {
160
+ map.set(entity.id, entity);
161
+ }
162
+ return map;
163
+ },
164
+ (id) => `entity:${id}`
165
+ );
166
+ const rawEntities = ids.map((id) => resultsMap.get(id)).filter((e) => e !== void 0);
167
+ await prefetchRelatedEntities(rawEntities, { next: options?.next, config: options?.config });
168
+ return rawEntities.map((e) => transformEntity(e, lang));
169
+ }
170
+ async function getFansUnitedCompetitions(options = {}) {
171
+ const lang = resolveLanguage(options);
172
+ const params = {
173
+ content_type: "competition",
174
+ query: options.query,
175
+ limit: options.limit?.toString(),
176
+ page: options.page?.toString(),
177
+ sport: options.sport
178
+ };
179
+ const cacheKey = `competitions:${hashParams(params)}`;
180
+ const result = await cached(
181
+ cacheKey,
182
+ "competitions",
183
+ () => searchHttp.get({
184
+ path: "/v1/entities/search",
185
+ params,
186
+ next: options.next,
187
+ config: options.config
188
+ })
189
+ );
190
+ cacheIndividualEntities(result.data);
191
+ await prefetchCountries(result.data, { next: options.next, config: options.config });
192
+ const transformed = result.data.map((e) => transformCompetitionSummary(e, lang));
193
+ return { data: transformed, pagination: result.meta.pagination };
194
+ }
195
+ async function getFansUnitedTeamsByCountry(countryId, options = {}) {
196
+ const lang = resolveLanguage(options);
197
+ const params = {
198
+ content_type: "team",
199
+ relationship: "COUNTRY",
200
+ value: countryId,
201
+ query: options.query,
202
+ limit: options.limit?.toString(),
203
+ page: options.page?.toString(),
204
+ sport: options.sport
205
+ };
206
+ const cacheKey = `teams:country:${countryId}:${hashParams(params)}`;
207
+ const result = await cached(
208
+ cacheKey,
209
+ "teams",
210
+ () => searchHttp.get({
211
+ path: "/v1/entities/search",
212
+ params,
213
+ next: options.next,
214
+ config: options.config
215
+ })
216
+ );
217
+ cacheIndividualEntities(result.data);
218
+ await prefetchCountries(result.data, { next: options.next, config: options.config });
219
+ const transformed = result.data.map((e) => transformTeamSummary(e, lang));
220
+ return { data: transformed, pagination: result.meta.pagination };
221
+ }
222
+ async function getFansUnitedTeamsByCompetition(competitionId, options = {}) {
223
+ const lang = resolveLanguage(options);
224
+ const params = {
225
+ content_type: "team",
226
+ relationship: "COMPETITION",
227
+ value: competitionId,
228
+ query: options.query,
229
+ limit: options.limit?.toString(),
230
+ page: options.page?.toString(),
231
+ sport: options.sport
232
+ };
233
+ const cacheKey = `teams:competition:${competitionId}:${hashParams(params)}`;
234
+ const result = await cached(
235
+ cacheKey,
236
+ "teams",
237
+ () => searchHttp.get({
238
+ path: "/v1/entities/search",
239
+ params,
240
+ next: options.next,
241
+ config: options.config
242
+ })
243
+ );
244
+ cacheIndividualEntities(result.data);
245
+ await prefetchCountries(result.data, { next: options.next, config: options.config });
246
+ const transformed = result.data.map((e) => transformTeamSummary(e, lang));
247
+ return { data: transformed, pagination: result.meta.pagination };
248
+ }
249
+ async function getFansUnitedCountries(options = {}) {
250
+ const lang = resolveLanguage(options);
251
+ const params = {
252
+ content_type: "country",
253
+ query: options.query,
254
+ limit: options.limit?.toString(),
255
+ page: options.page?.toString(),
256
+ sport: options.sport
257
+ };
258
+ const cacheKey = `countries:${hashParams(params)}`;
259
+ const result = await cached(
260
+ cacheKey,
261
+ "countries",
262
+ () => searchHttp.get({
263
+ path: "/v1/entities/search",
264
+ params,
265
+ next: options.next,
266
+ config: options.config
267
+ })
268
+ );
269
+ cacheIndividualEntities(result.data);
270
+ const transformed = result.data.map((e) => transformCountrySummary(e, lang));
271
+ return { data: transformed, pagination: result.meta.pagination };
272
+ }
273
+ async function getFansUnitedVenues(options = {}) {
274
+ const lang = resolveLanguage(options);
275
+ const params = {
276
+ content_type: "venue",
277
+ query: options.query,
278
+ limit: options.limit?.toString(),
279
+ page: options.page?.toString(),
280
+ sport: options.sport
281
+ };
282
+ const cacheKey = `venues:${hashParams(params)}`;
283
+ const result = await cached(
284
+ cacheKey,
285
+ "venues",
286
+ () => searchHttp.get({
287
+ path: "/v1/entities/search",
288
+ params,
289
+ next: options.next,
290
+ config: options.config
291
+ })
292
+ );
293
+ cacheIndividualEntities(result.data);
294
+ await prefetchCountries(result.data, { next: options.next, config: options.config });
295
+ const transformed = result.data.map((e) => transformVenueSummary(e, lang));
296
+ return { data: transformed, pagination: result.meta.pagination };
297
+ }
298
+ export {
299
+ getFansUnitedCompetitions,
300
+ getFansUnitedCountries,
301
+ getFansUnitedEntitiesByIds,
302
+ getFansUnitedEntityById,
303
+ getFansUnitedSearchEntities,
304
+ getFansUnitedTeamsByCompetition,
305
+ getFansUnitedTeamsByCountry,
306
+ getFansUnitedVenues
307
+ };
308
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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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"}