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
@@ -4,34 +4,139 @@
4
4
  * L2 (SQLite) is never statically imported here — it's injected at runtime
5
5
  * via initL2() so that browser bundles don't pull in better-sqlite3.
6
6
  */
7
- import type { CacheEntry, EntityCacheConfig, EntityType } from "./types";
8
- /** Interface that L2 stores must satisfy */
7
+ import type { CacheEntry, EntityCacheConfig, EntityType, MaybePromise } from "./types";
8
+ /** Interface that L2 stores must satisfy. Methods may be sync or async. */
9
9
  export interface L2Store {
10
10
  get isInitialized(): boolean;
11
- get<T>(key: string): CacheEntry<T> | undefined;
12
- set(key: string, entity: string, data: unknown): void;
11
+ get<T>(key: string): MaybePromise<CacheEntry<T> | undefined>;
12
+ set(key: string, entity: EntityType, data: unknown): MaybePromise<void>;
13
13
  setMany(entries: {
14
14
  key: string;
15
- entity: string;
15
+ entity: EntityType;
16
16
  data: unknown;
17
- }[]): void;
18
- cleanup(entity: string, maxTTLSeconds: number): number;
19
- clear(): void;
17
+ }[]): MaybePromise<void>;
18
+ cleanup(entity: EntityType, maxTTLSeconds: number): MaybePromise<number>;
19
+ clear(): MaybePromise<void>;
20
20
  }
21
21
  /**
22
- * Initialize L2 cache layer. Call on server startup.
23
- * Client-side apps skip this L2 is never loaded.
22
+ * Initialize the L2 cache layer. Call once at server startup; the binding
23
+ * is process-wide and replaces any previously-set store.
24
+ *
25
+ * In browser bundles, never call this — L2 is opt-in and the cache will
26
+ * operate L1-only when uninitialized (correct, just slower).
27
+ *
28
+ * In multi-instance deployments (e.g. Cloud Run), L2 should be a shared,
29
+ * durable store (Redis, DynamoDB, …) so a warm cache from one instance
30
+ * serves every other instance. A reference Redis adapter is at
31
+ * `src/lib/cache/__tests__/redis-l2-store.ts`.
32
+ *
33
+ * @example Next.js instrumentation hook
34
+ * ```ts
35
+ * // instrumentation.ts
36
+ * export async function register() {
37
+ * if (process.env.NEXT_RUNTIME !== "nodejs") return;
38
+ * const { initL2 } = await import("fansunited-data-layer");
39
+ * const { createRedisL2Store } = await import("./src/lib/cache/redisL2Store");
40
+ * const { getRedis } = await import("./src/lib/redis");
41
+ * initL2(createRedisL2Store({ client: getRedis() }));
42
+ * }
43
+ * ```
44
+ *
45
+ * @see {@link L2Store} for the interface a custom store must satisfy.
24
46
  */
25
47
  export declare function initL2(store: L2Store): void;
26
48
  /** Get the L2 store (if initialized) */
27
49
  export declare function getL2(): L2Store | null;
28
50
  declare const ENTITY_TTL_CONFIG: Record<EntityType, EntityCacheConfig>;
29
51
  /**
30
- * Single-key cache-through with SWR (Stale-While-Revalidate)
52
+ * Replace the TTL config for an entity type at runtime. The new values
53
+ * apply to subsequent `cached()` / `cachedBatch()` calls; existing L2
54
+ * entries keep whatever TTL they were written with.
55
+ *
56
+ * Useful for:
57
+ * - per-environment tuning (dev: short TTLs to see changes; prod: long)
58
+ * - overriding ahead of a known traffic spike
59
+ * - tests that need to simulate stale / expired entries in seconds
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * setEntityTTL("sportsCompetition", { staleTTL: 30, maxTTL: 600 });
64
+ * ```
65
+ *
66
+ * @see ../README.md § 7 for the full list of default TTLs.
67
+ */
68
+ export declare function setEntityTTL(entity: EntityType, config: EntityCacheConfig): void;
69
+ /**
70
+ * Read the current TTL config for an entity type.
71
+ *
72
+ * Primarily for L2 adapters that translate `entity` into an underlying
73
+ * eviction TTL (e.g. Redis `EX` seconds = `maxTTL`). The returned object
74
+ * is a defensive copy — mutating it has no effect on the manager.
75
+ *
76
+ * @throws when called with an entity name not in the config.
77
+ */
78
+ export declare function getEntityTTL(entity: EntityType): EntityCacheConfig;
79
+ /**
80
+ * Single-key cache-through with stale-while-revalidate.
81
+ *
82
+ * Flow:
83
+ * 1. L1 hit, fresh (< staleTTL) → return.
84
+ * 2. L1 hit, stale but valid (< maxTTL) → return + kick background refresh.
85
+ * 3. L1 miss, L2 hit, fresh → promote to L1 + return.
86
+ * 4. L1 miss, L2 hit, stale but valid → promote + return + background refresh.
87
+ * 5. Full miss → await `fetcher`, populate L1+L2, return.
88
+ *
89
+ * Background refreshes share a per-key in-flight set, so concurrent
90
+ * callers don't trigger a thundering herd of upstream fetches.
91
+ *
92
+ * The `key` must include the {@link CACHE_KEY_PREFIX} (`"fudl:"`) by
93
+ * convention so it can be SCANned safely in a shared Redis instance.
94
+ *
95
+ * @param key Fully-qualified cache key (e.g. `"fudl:sports:competition:fb:c:1:active"`).
96
+ * @param entity Entity type — drives the SWR window via `ENTITY_TTL_CONFIG`.
97
+ * @param fetcher Upstream call, invoked on miss or background refresh.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const data = await cached(
102
+ * `${CACHE_KEY_PREFIX}sports:competition:${id}:active`,
103
+ * "sportsCompetition",
104
+ * () => fetchFromSportsApi(id),
105
+ * );
106
+ * ```
31
107
  */
32
108
  export declare function cached<T>(key: string, entity: EntityType, fetcher: () => Promise<T>): Promise<T>;
33
109
  /**
34
- * Smart batch cache only fetches uncached IDs from the API
110
+ * Multi-key cache-through with stale-while-revalidate.
111
+ *
112
+ * For each `id`, the cache is checked (L1, then L2) and only the *missing*
113
+ * IDs are passed to `batchFetcher` in a single upstream call. Stale-but-
114
+ * valid entries are returned immediately and refreshed in the background
115
+ * per-key, just like {@link cached}.
116
+ *
117
+ * Why a separate function from `cached`? An N-ID lookup is one upstream
118
+ * batch request, not N parallel single-key calls — which is the whole
119
+ * reason the Search API supports `?ids=…,…` in the first place.
120
+ *
121
+ * @param ids IDs to resolve, in request order.
122
+ * @param entity Entity type — drives the SWR window.
123
+ * @param batchFetcher Called with the subset of IDs not in cache.
124
+ * Must return a `Map<id, value>` (missing IDs okay).
125
+ * @param keyFn Builds a fully-qualified cache key from an ID.
126
+ * Convention: `(id) => \`${CACHE_KEY_PREFIX}entity:${id}\``.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const entities = await cachedBatch(
131
+ * ids,
132
+ * "search",
133
+ * async (missingIds) => {
134
+ * const resp = await searchApi.get({ ids: missingIds, limit: missingIds.length });
135
+ * return new Map(resp.data.map((e) => [e.id, e]));
136
+ * },
137
+ * (id) => `${CACHE_KEY_PREFIX}entity:${id}`,
138
+ * );
139
+ * ```
35
140
  */
36
141
  export declare function cachedBatch<T>(ids: string[], entity: EntityType, batchFetcher: (missingIds: string[]) => Promise<Map<string, T>>, keyFn: (id: string) => string): Promise<Map<string, T>>;
37
142
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../src/lib/cache/cache-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEzE,4CAA4C;AAC5C,MAAM,WAAW,OAAO;IACpB,IAAI,aAAa,IAAI,OAAO,CAAC;IAC7B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACtD,OAAO,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;IACzE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;IACvD,KAAK,IAAI,IAAI,CAAC;CACjB;AAKD;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE3C;AAED,wCAAwC;AACxC,wBAAgB,KAAK,IAAI,OAAO,GAAG,IAAI,CAEtC;AAED,QAAA,MAAM,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAQ5D,CAAC;AAwCF;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoCtG;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EAAE,EACb,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAC/D,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAC9B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CA6DzB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE5C;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../src/lib/cache/cache-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvF,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACpB,IAAI,aAAa,IAAI,OAAO,CAAC;IAC7B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC7D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3F,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACzE,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;CAC/B;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE3C;AAED,wCAAwC;AACxC,wBAAgB,KAAK,IAAI,OAAO,GAAG,IAAI,CAEtC;AAED,QAAA,MAAM,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAS5D,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAEhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,iBAAiB,CAElE;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoCtG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EAAE,EACb,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAC/D,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAC9B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CA6DzB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE5C;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -4,14 +4,21 @@ function initL2(store) {
4
4
  l2 = store;
5
5
  }
6
6
  const ENTITY_TTL_CONFIG = {
7
- competitions: { staleTTL: 24 * 3600, maxTTL: 72 * 3600 },
8
- teams: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },
9
- athletes: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },
10
- venues: { staleTTL: 72 * 3600, maxTTL: 168 * 3600 },
11
- countries: { staleTTL: 96 * 3600, maxTTL: 168 * 3600 },
12
- coaches: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },
13
- search: { staleTTL: 300, maxTTL: 1800 }
7
+ competitions: { staleTTL: 8 * 3600, maxTTL: 72 * 3600 },
8
+ teams: { staleTTL: 8 * 3600, maxTTL: 48 * 3600 },
9
+ athletes: { staleTTL: 8 * 3600, maxTTL: 48 * 3600 },
10
+ venues: { staleTTL: 7 * 24 * 3600, maxTTL: 14 * 24 * 3600 },
11
+ countries: { staleTTL: 7 * 24 * 3600, maxTTL: 14 * 24 * 3600 },
12
+ coaches: { staleTTL: 24 * 3600, maxTTL: 72 * 3600 },
13
+ search: { staleTTL: 8 * 3600, maxTTL: 2 * 24 * 3600 },
14
+ sportsCompetition: { staleTTL: 5 * 60, maxTTL: 3600 }
14
15
  };
16
+ function setEntityTTL(entity, config) {
17
+ ENTITY_TTL_CONFIG[entity] = { ...config };
18
+ }
19
+ function getEntityTTL(entity) {
20
+ return { ...getConfig(entity) };
21
+ }
15
22
  const refreshing = /* @__PURE__ */ new Set();
16
23
  function getConfig(entity) {
17
24
  const config = ENTITY_TTL_CONFIG[entity];
@@ -29,10 +36,10 @@ function isExpired(entry, maxTTL) {
29
36
  function backgroundRefresh(key, entity, fetcher) {
30
37
  if (refreshing.has(key)) return;
31
38
  refreshing.add(key);
32
- fetcher().then((data) => {
39
+ fetcher().then(async (data) => {
33
40
  memoryStore.set(key, data);
34
41
  if (l2?.isInitialized) {
35
- l2.set(key, entity, data);
42
+ await l2.set(key, entity, data);
36
43
  }
37
44
  }).catch((err) => {
38
45
  console.error(`[cache] Background refresh failed for ${key}:`, err);
@@ -53,7 +60,7 @@ async function cached(key, entity, fetcher) {
53
60
  }
54
61
  }
55
62
  if (l2?.isInitialized) {
56
- const l2Entry = l2.get(key);
63
+ const l2Entry = await l2.get(key);
57
64
  if (l2Entry && !isExpired(l2Entry, maxTTL)) {
58
65
  memoryStore.set(key, l2Entry.data);
59
66
  if (isFresh(l2Entry, staleTTL)) {
@@ -66,7 +73,7 @@ async function cached(key, entity, fetcher) {
66
73
  const data = await fetcher();
67
74
  memoryStore.set(key, data);
68
75
  if (l2?.isInitialized) {
69
- l2.set(key, entity, data);
76
+ await l2.set(key, entity, data);
70
77
  }
71
78
  return data;
72
79
  }
@@ -91,7 +98,7 @@ async function cachedBatch(ids, entity, batchFetcher, keyFn) {
91
98
  found = true;
92
99
  }
93
100
  if (!found && l2?.isInitialized) {
94
- const l2Entry = l2.get(key);
101
+ const l2Entry = await l2.get(key);
95
102
  if (l2Entry && !isExpired(l2Entry, maxTTL)) {
96
103
  memoryStore.set(key, l2Entry.data);
97
104
  results.set(id, l2Entry.data);
@@ -116,7 +123,7 @@ async function cachedBatch(ids, entity, batchFetcher, keyFn) {
116
123
  const key = keyFn(id);
117
124
  memoryStore.set(key, data);
118
125
  if (l2?.isInitialized) {
119
- l2.set(key, entity, data);
126
+ await l2.set(key, entity, data);
120
127
  }
121
128
  results.set(id, data);
122
129
  }
@@ -130,7 +137,9 @@ export {
130
137
  ENTITY_TTL_CONFIG,
131
138
  cached,
132
139
  cachedBatch,
140
+ getEntityTTL,
133
141
  initL2,
134
- invalidate
142
+ invalidate,
143
+ setEntityTTL
135
144
  };
136
145
  //# sourceMappingURL=cache-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-manager.js","sources":["../../src/lib/cache/cache-manager.ts"],"sourcesContent":["/**\n * Cache Manager - Orchestrates L1 (memory) + optional L2 with SWR pattern\n *\n * L2 (SQLite) is never statically imported here — it's injected at runtime\n * via initL2() so that browser bundles don't pull in better-sqlite3.\n */\n\nimport { memoryStore } from \"./memory-store\";\nimport type { CacheEntry, EntityCacheConfig, EntityType } from \"./types\";\n\n/** Interface that L2 stores must satisfy */\nexport interface L2Store {\n get isInitialized(): boolean;\n get<T>(key: string): CacheEntry<T> | undefined;\n set(key: string, entity: string, data: unknown): void;\n setMany(entries: { key: string; entity: string; data: unknown }[]): void;\n cleanup(entity: string, maxTTLSeconds: number): number;\n clear(): void;\n}\n\n/** The active L2 store — null until initL2() is called */\nlet l2: L2Store | null = null;\n\n/**\n * Initialize L2 cache layer. Call on server startup.\n * Client-side apps skip this — L2 is never loaded.\n */\nexport function initL2(store: L2Store): void {\n l2 = store;\n}\n\n/** Get the L2 store (if initialized) */\nexport function getL2(): L2Store | null {\n return l2;\n}\n\nconst ENTITY_TTL_CONFIG: Record<EntityType, EntityCacheConfig> = {\n competitions: { staleTTL: 24 * 3600, maxTTL: 72 * 3600 },\n teams: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },\n athletes: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },\n venues: { staleTTL: 72 * 3600, maxTTL: 168 * 3600 },\n countries: { staleTTL: 96 * 3600, maxTTL: 168 * 3600 },\n coaches: { staleTTL: 24 * 3600, maxTTL: 48 * 3600 },\n search: { staleTTL: 300, maxTTL: 1800 },\n};\n\n/** Set of keys currently being refreshed in the background (thundering herd prevention) */\nconst refreshing = new Set<string>();\n\nfunction getConfig(entity: EntityType): EntityCacheConfig {\n const config = ENTITY_TTL_CONFIG[entity];\n if (!config) {\n throw new Error(`Unknown entity type: ${entity}`);\n }\n return config;\n}\n\nfunction isFresh(entry: CacheEntry<unknown>, staleTTL: number): boolean {\n return Date.now() - entry.storedAt < staleTTL * 1000;\n}\n\nfunction isExpired(entry: CacheEntry<unknown>, maxTTL: number): boolean {\n return Date.now() - entry.storedAt >= maxTTL * 1000;\n}\n\nfunction backgroundRefresh<T>(key: string, entity: EntityType, fetcher: () => Promise<T>): void {\n if (refreshing.has(key)) return;\n refreshing.add(key);\n\n fetcher()\n .then((data) => {\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n l2.set(key, entity, data);\n }\n })\n .catch((err) => {\n console.error(`[cache] Background refresh failed for ${key}:`, err);\n })\n .finally(() => {\n refreshing.delete(key);\n });\n}\n\n/**\n * Single-key cache-through with SWR (Stale-While-Revalidate)\n */\nexport async function cached<T>(key: string, entity: EntityType, fetcher: () => Promise<T>): Promise<T> {\n const { staleTTL, maxTTL } = getConfig(entity);\n\n // L1 check\n const l1 = memoryStore.get<T>(key);\n if (l1) {\n if (isFresh(l1, staleTTL)) {\n return l1.data;\n }\n if (!isExpired(l1, maxTTL)) {\n backgroundRefresh(key, entity, fetcher);\n return l1.data;\n }\n }\n\n // L2 check\n if (l2?.isInitialized) {\n const l2Entry = l2.get<T>(key);\n if (l2Entry && !isExpired(l2Entry, maxTTL)) {\n // Promote to L1\n memoryStore.set(key, l2Entry.data);\n if (isFresh(l2Entry, staleTTL)) {\n return l2Entry.data;\n }\n backgroundRefresh(key, entity, fetcher);\n return l2Entry.data;\n }\n }\n\n // Full miss — await fetcher\n const data = await fetcher();\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n l2.set(key, entity, data);\n }\n return data;\n}\n\n/**\n * Smart batch cache — only fetches uncached IDs from the API\n */\nexport async function cachedBatch<T>(\n ids: string[],\n entity: EntityType,\n batchFetcher: (missingIds: string[]) => Promise<Map<string, T>>,\n keyFn: (id: string) => string\n): Promise<Map<string, T>> {\n const { staleTTL, maxTTL } = getConfig(entity);\n const results = new Map<string, T>();\n const missingIds: string[] = [];\n\n for (const id of ids) {\n const key = keyFn(id);\n let found = false;\n\n // L1 check\n const l1 = memoryStore.get<T>(key);\n if (l1 && !isExpired(l1, maxTTL)) {\n results.set(id, l1.data);\n if (!isFresh(l1, staleTTL)) {\n backgroundRefresh(key, entity, async () => {\n const fetched = await batchFetcher([id]);\n const item = fetched.get(id);\n if (!item) throw new Error(`Batch fetcher did not return ID: ${id}`);\n return item;\n });\n }\n found = true;\n }\n\n // L2 check\n if (!found && l2?.isInitialized) {\n const l2Entry = l2.get<T>(key);\n if (l2Entry && !isExpired(l2Entry, maxTTL)) {\n memoryStore.set(key, l2Entry.data);\n results.set(id, l2Entry.data);\n if (!isFresh(l2Entry, staleTTL)) {\n backgroundRefresh(key, entity, async () => {\n const fetched = await batchFetcher([id]);\n const item = fetched.get(id);\n if (!item) throw new Error(`Batch fetcher did not return ID: ${id}`);\n return item;\n });\n }\n found = true;\n }\n }\n\n if (!found) {\n missingIds.push(id);\n }\n }\n\n // Fetch missing IDs in a single batch\n if (missingIds.length > 0) {\n const fetched = await batchFetcher(missingIds);\n for (const [id, data] of fetched) {\n const key = keyFn(id);\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n l2.set(key, entity, data);\n }\n results.set(id, data);\n }\n }\n\n return results;\n}\n\n/**\n * Remove an entry from both cache layers\n */\nexport function invalidate(key: string): void {\n memoryStore.delete(key);\n}\n\n// Export for testing\nexport { ENTITY_TTL_CONFIG };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache-manager.js","sources":["../../src/lib/cache/cache-manager.ts"],"sourcesContent":["/**\n * Cache Manager - Orchestrates L1 (memory) + optional L2 with SWR pattern\n *\n * L2 (SQLite) is never statically imported here — it's injected at runtime\n * via initL2() so that browser bundles don't pull in better-sqlite3.\n */\n\nimport { memoryStore } from \"./memory-store\";\nimport type { CacheEntry, EntityCacheConfig, EntityType, MaybePromise } from \"./types\";\n\n/** Interface that L2 stores must satisfy. Methods may be sync or async. */\nexport interface L2Store {\n get isInitialized(): boolean;\n get<T>(key: string): MaybePromise<CacheEntry<T> | undefined>;\n set(key: string, entity: EntityType, data: unknown): MaybePromise<void>;\n setMany(entries: { key: string; entity: EntityType; data: unknown }[]): MaybePromise<void>;\n cleanup(entity: EntityType, maxTTLSeconds: number): MaybePromise<number>;\n clear(): MaybePromise<void>;\n}\n\n/** The active L2 store — null until initL2() is called */\nlet l2: L2Store | null = null;\n\n/**\n * Initialize the L2 cache layer. Call once at server startup; the binding\n * is process-wide and replaces any previously-set store.\n *\n * In browser bundles, never call this — L2 is opt-in and the cache will\n * operate L1-only when uninitialized (correct, just slower).\n *\n * In multi-instance deployments (e.g. Cloud Run), L2 should be a shared,\n * durable store (Redis, DynamoDB, …) so a warm cache from one instance\n * serves every other instance. A reference Redis adapter is at\n * `src/lib/cache/__tests__/redis-l2-store.ts`.\n *\n * @example Next.js instrumentation hook\n * ```ts\n * // instrumentation.ts\n * export async function register() {\n * if (process.env.NEXT_RUNTIME !== \"nodejs\") return;\n * const { initL2 } = await import(\"fansunited-data-layer\");\n * const { createRedisL2Store } = await import(\"./src/lib/cache/redisL2Store\");\n * const { getRedis } = await import(\"./src/lib/redis\");\n * initL2(createRedisL2Store({ client: getRedis() }));\n * }\n * ```\n *\n * @see {@link L2Store} for the interface a custom store must satisfy.\n */\nexport function initL2(store: L2Store): void {\n l2 = store;\n}\n\n/** Get the L2 store (if initialized) */\nexport function getL2(): L2Store | null {\n return l2;\n}\n\nconst ENTITY_TTL_CONFIG: Record<EntityType, EntityCacheConfig> = {\n competitions: { staleTTL: 8 * 3600, maxTTL: 72 * 3600 },\n teams: { staleTTL: 8 * 3600, maxTTL: 48 * 3600 },\n athletes: { staleTTL: 8 * 3600, maxTTL: 48 * 3600 },\n venues: { staleTTL: 7 * 24 * 3600, maxTTL: 14 * 24 * 3600 },\n countries: { staleTTL: 7 * 24 * 3600, maxTTL: 14 * 24 * 3600 },\n coaches: { staleTTL: 24 * 3600, maxTTL: 72 * 3600 },\n search: { staleTTL: 8 * 3600, maxTTL: 2 * 24 * 3600 },\n sportsCompetition: { staleTTL: 5 * 60, maxTTL: 3600 },\n};\n\n/**\n * Replace the TTL config for an entity type at runtime. The new values\n * apply to subsequent `cached()` / `cachedBatch()` calls; existing L2\n * entries keep whatever TTL they were written with.\n *\n * Useful for:\n * - per-environment tuning (dev: short TTLs to see changes; prod: long)\n * - overriding ahead of a known traffic spike\n * - tests that need to simulate stale / expired entries in seconds\n *\n * @example\n * ```ts\n * setEntityTTL(\"sportsCompetition\", { staleTTL: 30, maxTTL: 600 });\n * ```\n *\n * @see ../README.md § 7 for the full list of default TTLs.\n */\nexport function setEntityTTL(entity: EntityType, config: EntityCacheConfig): void {\n ENTITY_TTL_CONFIG[entity] = { ...config };\n}\n\n/**\n * Read the current TTL config for an entity type.\n *\n * Primarily for L2 adapters that translate `entity` into an underlying\n * eviction TTL (e.g. Redis `EX` seconds = `maxTTL`). The returned object\n * is a defensive copy — mutating it has no effect on the manager.\n *\n * @throws when called with an entity name not in the config.\n */\nexport function getEntityTTL(entity: EntityType): EntityCacheConfig {\n return { ...getConfig(entity) };\n}\n\n/** Set of keys currently being refreshed in the background (thundering herd prevention) */\nconst refreshing = new Set<string>();\n\nfunction getConfig(entity: EntityType): EntityCacheConfig {\n const config = ENTITY_TTL_CONFIG[entity];\n if (!config) {\n throw new Error(`Unknown entity type: ${entity}`);\n }\n return config;\n}\n\nfunction isFresh(entry: CacheEntry<unknown>, staleTTL: number): boolean {\n return Date.now() - entry.storedAt < staleTTL * 1000;\n}\n\nfunction isExpired(entry: CacheEntry<unknown>, maxTTL: number): boolean {\n return Date.now() - entry.storedAt >= maxTTL * 1000;\n}\n\nfunction backgroundRefresh<T>(key: string, entity: EntityType, fetcher: () => Promise<T>): void {\n if (refreshing.has(key)) return;\n refreshing.add(key);\n\n fetcher()\n .then(async (data) => {\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n await l2.set(key, entity, data);\n }\n })\n .catch((err) => {\n console.error(`[cache] Background refresh failed for ${key}:`, err);\n })\n .finally(() => {\n refreshing.delete(key);\n });\n}\n\n/**\n * Single-key cache-through with stale-while-revalidate.\n *\n * Flow:\n * 1. L1 hit, fresh (< staleTTL) → return.\n * 2. L1 hit, stale but valid (< maxTTL) → return + kick background refresh.\n * 3. L1 miss, L2 hit, fresh → promote to L1 + return.\n * 4. L1 miss, L2 hit, stale but valid → promote + return + background refresh.\n * 5. Full miss → await `fetcher`, populate L1+L2, return.\n *\n * Background refreshes share a per-key in-flight set, so concurrent\n * callers don't trigger a thundering herd of upstream fetches.\n *\n * The `key` must include the {@link CACHE_KEY_PREFIX} (`\"fudl:\"`) by\n * convention so it can be SCANned safely in a shared Redis instance.\n *\n * @param key Fully-qualified cache key (e.g. `\"fudl:sports:competition:fb:c:1:active\"`).\n * @param entity Entity type — drives the SWR window via `ENTITY_TTL_CONFIG`.\n * @param fetcher Upstream call, invoked on miss or background refresh.\n *\n * @example\n * ```ts\n * const data = await cached(\n * `${CACHE_KEY_PREFIX}sports:competition:${id}:active`,\n * \"sportsCompetition\",\n * () => fetchFromSportsApi(id),\n * );\n * ```\n */\nexport async function cached<T>(key: string, entity: EntityType, fetcher: () => Promise<T>): Promise<T> {\n const { staleTTL, maxTTL } = getConfig(entity);\n\n // L1 check\n const l1 = memoryStore.get<T>(key);\n if (l1) {\n if (isFresh(l1, staleTTL)) {\n return l1.data;\n }\n if (!isExpired(l1, maxTTL)) {\n backgroundRefresh(key, entity, fetcher);\n return l1.data;\n }\n }\n\n // L2 check\n if (l2?.isInitialized) {\n const l2Entry = await l2.get<T>(key);\n if (l2Entry && !isExpired(l2Entry, maxTTL)) {\n // Promote to L1\n memoryStore.set(key, l2Entry.data);\n if (isFresh(l2Entry, staleTTL)) {\n return l2Entry.data;\n }\n backgroundRefresh(key, entity, fetcher);\n return l2Entry.data;\n }\n }\n\n // Full miss — await fetcher\n const data = await fetcher();\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n await l2.set(key, entity, data);\n }\n return data;\n}\n\n/**\n * Multi-key cache-through with stale-while-revalidate.\n *\n * For each `id`, the cache is checked (L1, then L2) and only the *missing*\n * IDs are passed to `batchFetcher` in a single upstream call. Stale-but-\n * valid entries are returned immediately and refreshed in the background\n * per-key, just like {@link cached}.\n *\n * Why a separate function from `cached`? An N-ID lookup is one upstream\n * batch request, not N parallel single-key calls — which is the whole\n * reason the Search API supports `?ids=…,…` in the first place.\n *\n * @param ids IDs to resolve, in request order.\n * @param entity Entity type — drives the SWR window.\n * @param batchFetcher Called with the subset of IDs not in cache.\n * Must return a `Map<id, value>` (missing IDs okay).\n * @param keyFn Builds a fully-qualified cache key from an ID.\n * Convention: `(id) => \\`${CACHE_KEY_PREFIX}entity:${id}\\``.\n *\n * @example\n * ```ts\n * const entities = await cachedBatch(\n * ids,\n * \"search\",\n * async (missingIds) => {\n * const resp = await searchApi.get({ ids: missingIds, limit: missingIds.length });\n * return new Map(resp.data.map((e) => [e.id, e]));\n * },\n * (id) => `${CACHE_KEY_PREFIX}entity:${id}`,\n * );\n * ```\n */\nexport async function cachedBatch<T>(\n ids: string[],\n entity: EntityType,\n batchFetcher: (missingIds: string[]) => Promise<Map<string, T>>,\n keyFn: (id: string) => string\n): Promise<Map<string, T>> {\n const { staleTTL, maxTTL } = getConfig(entity);\n const results = new Map<string, T>();\n const missingIds: string[] = [];\n\n for (const id of ids) {\n const key = keyFn(id);\n let found = false;\n\n // L1 check\n const l1 = memoryStore.get<T>(key);\n if (l1 && !isExpired(l1, maxTTL)) {\n results.set(id, l1.data);\n if (!isFresh(l1, staleTTL)) {\n backgroundRefresh(key, entity, async () => {\n const fetched = await batchFetcher([id]);\n const item = fetched.get(id);\n if (!item) throw new Error(`Batch fetcher did not return ID: ${id}`);\n return item;\n });\n }\n found = true;\n }\n\n // L2 check\n if (!found && l2?.isInitialized) {\n const l2Entry = await l2.get<T>(key);\n if (l2Entry && !isExpired(l2Entry, maxTTL)) {\n memoryStore.set(key, l2Entry.data);\n results.set(id, l2Entry.data);\n if (!isFresh(l2Entry, staleTTL)) {\n backgroundRefresh(key, entity, async () => {\n const fetched = await batchFetcher([id]);\n const item = fetched.get(id);\n if (!item) throw new Error(`Batch fetcher did not return ID: ${id}`);\n return item;\n });\n }\n found = true;\n }\n }\n\n if (!found) {\n missingIds.push(id);\n }\n }\n\n // Fetch missing IDs in a single batch\n if (missingIds.length > 0) {\n const fetched = await batchFetcher(missingIds);\n for (const [id, data] of fetched) {\n const key = keyFn(id);\n memoryStore.set(key, data);\n if (l2?.isInitialized) {\n await l2.set(key, entity, data);\n }\n results.set(id, data);\n }\n }\n\n return results;\n}\n\n/**\n * Remove an entry from both cache layers\n */\nexport function invalidate(key: string): void {\n memoryStore.delete(key);\n}\n\n// Export for testing\nexport { ENTITY_TTL_CONFIG };\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Periodic L2 cache cleanup
3
3
  */
4
- export declare function runCleanup(): void;
4
+ export declare function runCleanup(): Promise<void>;
5
5
  export declare function startCleanupSchedule(intervalMs?: number): void;
6
6
  export declare function stopCleanupSchedule(): void;
7
7
  //# sourceMappingURL=cleanup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/lib/cache/cleanup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,UAAU,IAAI,IAAI,CAWjC;AAED,wBAAgB,oBAAoB,CAAC,UAAU,SAAiB,GAAG,IAAI,CAGtE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/lib/cache/cleanup.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAWhD;AAED,wBAAgB,oBAAoB,CAAC,UAAU,SAAiB,GAAG,IAAI,CAGtE;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C"}
package/cache/index.d.ts CHANGED
@@ -6,8 +6,9 @@
6
6
  * import { initSqliteStore, sqliteStore } from './cache/sqlite-store';
7
7
  */
8
8
  export { memoryStore } from "./memory-store";
9
- export { cached, cachedBatch, invalidate, initL2 } from "./cache-manager";
9
+ export { cached, cachedBatch, invalidate, initL2, setEntityTTL, getEntityTTL } from "./cache-manager";
10
10
  export type { L2Store } from "./cache-manager";
11
11
  export { runCleanup, startCleanupSchedule, stopCleanupSchedule } from "./cleanup";
12
- export type { CacheEntry, EntityCacheConfig, EntityType } from "./types";
12
+ export type { CacheEntry, EntityCacheConfig, EntityType, MaybePromise } from "./types";
13
+ export { CACHE_KEY_PREFIX } from "./types";
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC1E,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAClF,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtG,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAClF,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * L2 Cache - SQLite on-disk store (server-only)
3
3
  */
4
- import type { CacheEntry } from "./types";
4
+ import type { CacheEntry, EntityType } from "./types";
5
5
  export declare function initSqliteStore(dbPath?: string): void;
6
6
  export declare const sqliteStore: {
7
7
  readonly isInitialized: boolean;
8
8
  get<T>(key: string): CacheEntry<T> | undefined;
9
- set(key: string, entity: string, data: unknown): void;
9
+ set(key: string, entity: EntityType, data: unknown): void;
10
10
  setMany(entries: {
11
11
  key: string;
12
- entity: string;
12
+ entity: EntityType;
13
13
  data: unknown;
14
14
  }[]): void;
15
- cleanup(entity: string, maxTTLSeconds: number): number;
15
+ cleanup(entity: EntityType, maxTTLSeconds: number): number;
16
16
  clear(): void;
17
17
  close(): void;
18
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/lib/cache/sqlite-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAW1C,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CA4BrD;AAED,eAAO,MAAM,WAAW;4BACC,OAAO;QAIxB,CAAC,OAAO,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS;aAarC,MAAM,UAAU,MAAM,QAAQ,OAAO,GAAG,IAAI;qBASpC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;oBAgBxD,MAAM,iBAAiB,MAAM,GAAG,MAAM;aAQ7C,IAAI;aAIJ,IAAI;CAMhB,CAAC"}
1
+ {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/lib/cache/sqlite-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAWtD,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CA4BrD;AAED,eAAO,MAAM,WAAW;4BACC,OAAO;QAIxB,CAAC,OAAO,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,SAAS;aAarC,MAAM,UAAU,UAAU,QAAQ,OAAO,GAAG,IAAI;qBASxC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EAAE,GAAG,IAAI;oBAgB5D,UAAU,iBAAiB,MAAM,GAAG,MAAM;aAQjD,IAAI;aAIJ,IAAI;CAMhB,CAAC"}
package/cache/types.d.ts CHANGED
@@ -11,5 +11,13 @@ export interface EntityCacheConfig {
11
11
  /** Time in seconds before data is completely expired and must be re-fetched */
12
12
  maxTTL: number;
13
13
  }
14
- export type EntityType = "competitions" | "teams" | "athletes" | "venues" | "countries" | "coaches" | "search";
14
+ export type EntityType = "competitions" | "teams" | "athletes" | "venues" | "countries" | "coaches" | "search" | "sportsCompetition";
15
+ /** Convenience: a value that may or may not be wrapped in a Promise. */
16
+ export type MaybePromise<T> = T | Promise<T>;
17
+ /**
18
+ * Prefix for every cache key emitted by this library.
19
+ * Namespaces the data-layer's entries inside a shared store (Redis SCAN by `fudl:*`).
20
+ * Bump the literal (e.g. `"fudl:v2:"`) to invalidate every cached entry across deploys.
21
+ */
22
+ export declare const CACHE_KEY_PREFIX = "fudl:";
15
23
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/cache/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/cache/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,UAAU,GAChB,cAAc,GACd,OAAO,GACP,UAAU,GACV,QAAQ,GACR,WAAW,GACX,SAAS,GACT,QAAQ,GACR,mBAAmB,CAAC;AAE1B,wEAAwE;AACxE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAC"}
package/cache/types.js ADDED
@@ -0,0 +1,5 @@
1
+ const CACHE_KEY_PREFIX = "fudl:";
2
+ export {
3
+ CACHE_KEY_PREFIX
4
+ };
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":["../../src/lib/cache/types.ts"],"sourcesContent":["/**\n * Shared cache types\n */\n\nexport interface CacheEntry<T> {\n data: T;\n storedAt: number; // Unix timestamp in ms\n}\n\nexport interface EntityCacheConfig {\n /** Time in seconds before data is considered stale (triggers background refresh) */\n staleTTL: number;\n /** Time in seconds before data is completely expired and must be re-fetched */\n maxTTL: number;\n}\n\nexport type EntityType =\n | \"competitions\"\n | \"teams\"\n | \"athletes\"\n | \"venues\"\n | \"countries\"\n | \"coaches\"\n | \"search\"\n | \"sportsCompetition\";\n\n/** Convenience: a value that may or may not be wrapped in a Promise. */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * Prefix for every cache key emitted by this library.\n * Namespaces the data-layer's entries inside a shared store (Redis SCAN by `fudl:*`).\n * Bump the literal (e.g. `\"fudl:v2:\"`) to invalidate every cached entry across deploys.\n */\nexport const CACHE_KEY_PREFIX = \"fudl:\";\n"],"names":[],"mappings":"AAkCO,MAAM,mBAAmB;"}
@@ -1,10 +1,11 @@
1
1
  import { getConfig, isConfigured, setConfig } from "./config/index.js";
2
2
  import { memoryStore } from "./cache/memory-store.js";
3
+ import { CACHE_KEY_PREFIX } from "./cache/types.js";
3
4
  import { GOAL_EVENT_TYPES } from "./utilities/stats/core/types.js";
4
5
  import { addProviderRef, getProviderRefId, toProviderRefArray } from "./api/sportal365-sports/shared/providerRef.helper.js";
5
6
  import { aggregatePlayerStatisticsFromMatches, getAllPlayerStatisticsFromMatches, getMostCardedPlayersFromMatches, getTopAssistersFromMatches, getTopGoalContributorsFromMatches, getTopScorersFromMatches } from "./helpers/player.helpers.js";
6
7
  import { analyzeMatch, calcAverage, calcPercentage, formatAsAverage, formatPossessionPercentage, formatStatValue, formatWithAverage, getOpponentScore, getTeamScore, isMatchFinished, isTeamAway, isTeamHome, isTeamInMatch } from "./utilities/stats/core/helpers.js";
7
- import { cached, cachedBatch, initL2, invalidate } from "./cache/cache-manager.js";
8
+ import { cached, cachedBatch, getEntityTTL, initL2, invalidate, setEntityTTL } from "./cache/cache-manager.js";
8
9
  import { calculateH2HStats, getRecentH2HMeetings } from "./utilities/stats/match/headToHead.js";
9
10
  import { calculateStreak, getTeamStreaks, getTeamStreaksComparison, streakFilters } from "./utilities/stats/team/streaks.js";
10
11
  import { getActiveSeason } from "./helpers/competition.helpers.js";
@@ -18,6 +19,9 @@ import { getFansUnitedFootballPlayer, getFansUnitedFootballPlayers } from "./api
18
19
  import { getFansUnitedFootballSearch } from "./api/fansunited/football/search/index.js";
19
20
  import { getFansUnitedFootballTeam, getFansUnitedFootballTeams } from "./api/fansunited/football/teams/index.js";
20
21
  import { getFansUnitedSportsCompetition } from "./api/fansunited/sports/competition/index.js";
22
+ import { getFansUnitedSportsCompetitionHydrated } from "./api/fansunited/sports/competition/hydrated.js";
23
+ import { getFansUnitedSportsLivescore } from "./api/fansunited/sports/livescore/index.js";
24
+ import { getFansUnitedSportsLivescoreHydrated } from "./api/fansunited/sports/livescore/hydrated.js";
21
25
  import { getFootballCompetition, getFootballSeasonDetails } from "./api/sportal365-sports/football/competitions/index.js";
22
26
  import { getFootballLivescore, getFootballMatch, getFootballMatchCommentary, getFootballMatchEvents, getFootballMatchLineups, getFootballMatchOdds, getFootballMatchStatistics, getFootballMatches } from "./api/sportal365-sports/football/matches/index.js";
23
27
  import { getFootballPlayerCareerStatistics, getFootballPlayerRecentStatistics, getFootballPlayerSeasonStatistics, getFootballPlayerSeasonStatisticsByPlayerIds } from "./api/sportal365-sports/football/statistics/index.js";
@@ -38,6 +42,7 @@ import { search } from "./api/sportal365-sports/search/index.js";
38
42
  import { searchFootball } from "./api/sportal365-sports/football/search/index.js";
39
43
  import { useAllPlayerStatisticsFromMatches, useMostCardedPlayersFromMatches, usePlayerStatistics, usePlayerStatisticsMap, useTopAssistersFromMatches, useTopGoalContributorsFromMatches, useTopScorersFromMatches } from "./helpers/player.hooks.js";
40
44
  export {
45
+ CACHE_KEY_PREFIX,
41
46
  GOAL_EVENT_TYPES,
42
47
  addProviderRef,
43
48
  aggregatePlayerStatisticsFromMatches,
@@ -57,6 +62,7 @@ export {
57
62
  getBasketballLivescore,
58
63
  getBatchMatchOdds,
59
64
  getConfig,
65
+ getEntityTTL,
60
66
  getFansUnitedCompetitions,
61
67
  getFansUnitedCountries,
62
68
  getFansUnitedEntitiesByIds,
@@ -76,6 +82,9 @@ export {
76
82
  getFansUnitedFootballTeams,
77
83
  getFansUnitedSearchEntities,
78
84
  getFansUnitedSportsCompetition,
85
+ getFansUnitedSportsCompetitionHydrated,
86
+ getFansUnitedSportsLivescore,
87
+ getFansUnitedSportsLivescoreHydrated,
79
88
  getFansUnitedTeamsByCompetition,
80
89
  getFansUnitedTeamsByCountry,
81
90
  getFansUnitedVenues,
@@ -139,6 +148,7 @@ export {
139
148
  search,
140
149
  searchFootball,
141
150
  setConfig,
151
+ setEntityTTL,
142
152
  streakFilters,
143
153
  toProviderRefArray,
144
154
  useAllPlayerStatisticsFromMatches,
@@ -1 +1 @@
1
- {"version":3,"file":"fansunited-data-layer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"fansunited-data-layer.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/index.d.ts CHANGED
@@ -26,19 +26,19 @@
26
26
  export { setConfig, getConfig, isConfigured, type DataLayerConfig, type Sportal365SportsConfig, type PayloadConfig, } from "./config";
27
27
  export { getFootballMatch, getFootballMatchEvents, getFootballMatchLineups, getFootballMatchOdds, getFootballMatchStatistics, getFootballMatchCommentary, getFootballMatches, getFootballLivescore, getBasketballLivescore, getTennisLivescore, getFootballTeam, getFootballTeamSquad, getFootballCompetition, getFootballSeasonDetails, getFootballStandings, getFootballPlayerSeasonStatistics, getFootballPlayerSeasonStatisticsByPlayerIds, getFootballPlayerCareerStatistics, getFootballPlayerRecentStatistics, getTeamSeasonStatistics, getSportal365Standings, searchFootball, } from "./api/sportal365-sports";
28
28
  export { search } from "./api/sportal365-sports";
29
- export { getFansUnitedFootballCompetitions, getFansUnitedFootballCompetition, getFansUnitedFootballTeam, getFansUnitedFootballTeams, getFansUnitedFootballPlayer, getFansUnitedFootballPlayers, getFansUnitedFootballMatch, getFansUnitedFootballMatches, getFansUnitedFootballTeamNextMatch, getFansUnitedFootballTeamPreviousMatch, getFansUnitedFootballPlayerNextMatch, getFansUnitedFootballPlayerPreviousMatch, getFansUnitedFootballSearch, getFansUnitedSearchEntities, getFansUnitedEntityById, getFansUnitedEntitiesByIds, getFansUnitedCompetitions, getFansUnitedTeamsByCountry, getFansUnitedTeamsByCompetition, getFansUnitedCountries, getFansUnitedVenues, getFansUnitedSportsCompetition, } from "./api/fansunited";
29
+ export { getFansUnitedFootballCompetitions, getFansUnitedFootballCompetition, getFansUnitedFootballTeam, getFansUnitedFootballTeams, getFansUnitedFootballPlayer, getFansUnitedFootballPlayers, getFansUnitedFootballMatch, getFansUnitedFootballMatches, getFansUnitedFootballTeamNextMatch, getFansUnitedFootballTeamPreviousMatch, getFansUnitedFootballPlayerNextMatch, getFansUnitedFootballPlayerPreviousMatch, getFansUnitedFootballSearch, getFansUnitedSearchEntities, getFansUnitedEntityById, getFansUnitedEntitiesByIds, getFansUnitedCompetitions, getFansUnitedTeamsByCountry, getFansUnitedTeamsByCompetition, getFansUnitedCountries, getFansUnitedVenues, getFansUnitedSportsCompetition, getFansUnitedSportsCompetitionHydrated, getFansUnitedSportsLivescore, getFansUnitedSportsLivescoreHydrated, } from "./api/fansunited";
30
30
  export { getLeaderboardMatches, getLeaderboardTeamMatches, getLeaderboardTemplate, getBatchMatchOdds, } from "./api/fansunited-sdk";
31
31
  export type { GetBatchMatchOddsOptions } from "./api/fansunited-sdk";
32
- export type { GetFootballCompetitionsOptions, GetFootballCompetitionOptions as GetFansUnitedFootballCompetitionOptions, GetFootballTeamOptions as GetFansUnitedFootballTeamOptions, GetFootballTeamsOptions as GetFansUnitedFootballTeamsOptions, GetFootballPlayerOptions as GetFansUnitedFootballPlayerOptions, GetFootballPlayersOptions as GetFansUnitedFootballPlayersOptions, GetFootballMatchOptions as GetFansUnitedFootballMatchOptions, GetFootballMatchesOptions as GetFansUnitedFootballMatchesOptions, GetFootballSearchOptions as GetFansUnitedFootballSearchOptions, SearchEntityType as FansUnitedSearchEntityType, FansUnitedFootballSearchResult, SearchMode, EntityContentType, EntitySearchOptions, GetEntityByIdOptions, GetEntitiesByIdsOptions, GetCompetitionsOptions, GetTeamsByCountryOptions, GetTeamsByCompetitionOptions, GetCountriesOptions, GetVenuesOptions, RawSearchEntity, SearchEntityResult, SearchEntitySummary, EntitySearchResponse, PaginationMeta, PaginatedResult, GetSportsCompetitionOptions, } from "./api/fansunited";
32
+ export type { GetFootballCompetitionsOptions, GetFootballCompetitionOptions as GetFansUnitedFootballCompetitionOptions, GetFootballTeamOptions as GetFansUnitedFootballTeamOptions, GetFootballTeamsOptions as GetFansUnitedFootballTeamsOptions, GetFootballPlayerOptions as GetFansUnitedFootballPlayerOptions, GetFootballPlayersOptions as GetFansUnitedFootballPlayersOptions, GetFootballMatchOptions as GetFansUnitedFootballMatchOptions, GetFootballMatchesOptions as GetFansUnitedFootballMatchesOptions, GetFootballSearchOptions as GetFansUnitedFootballSearchOptions, SearchEntityType as FansUnitedSearchEntityType, FansUnitedFootballSearchResult, SearchMode, EntityContentType, EntitySearchOptions, GetEntityByIdOptions, GetEntitiesByIdsOptions, GetCompetitionsOptions, GetTeamsByCountryOptions, GetTeamsByCompetitionOptions, GetCountriesOptions, GetVenuesOptions, RawSearchEntity, SearchEntityResult, SearchEntitySummary, EntitySearchResponse, PaginationMeta, PaginatedResult, GetSportsCompetitionOptions, GetSportsCompetitionHydratedOptions, GetSportsLivescoreOptions, GetSportsLivescoreHydratedOptions, FUSportsCompetitionHydrated, FUSportsLivescoreHydrated, } from "./api/fansunited";
33
33
  export { getProviderRefId, addProviderRef, toProviderRefArray } from "./api/sportal365-sports/shared";
34
34
  export type { GetFootballMatchOptions, GetFootballMatchEventsOptions, GetFootballMatchLineupsOptions, GetFootballMatchOddsOptions, GetFootballMatchStatisticsOptions, GetFootballMatchCommentaryOptions, GetFootballMatchesOptions, GetFootballLivescoreOptions, GetBasketballLivescoreOptions, BasketballMatchStatusType, GetTennisLivescoreOptions, TennisMatchStatusType, TennisMatchType, TennisGender, GetFootballTeamOptions, GetFootballTeamSquadOptions, GetFootballCompetitionOptions, GetFootballSeasonDetailsOptions, GetFootballStandingsOptions, GetFootballPlayerSeasonStatisticsOptions, GetFootballPlayerSeasonStatisticsByPlayerIdsOptions, GetFootballPlayerCareerStatisticsOptions, GetFootballPlayerRecentStatisticsOptions, GetTeamSeasonStatisticsOptions, GetSportal365StandingsOptions, StandingsSport, StandingsCoverageType, GetFootballSearchOptions, SearchEntityType, GetSportsSearchOptions, SportType, SportsSearchEntityType, FootballStandingsExpandOption, OddType, ScopeType, OddFormat, MarketType, OptionalMatchData, MatchStatusType, SortDirection, SelectionFilter, NextCacheOptions, } from "./api/sportal365-sports";
35
- export type { FUSportsCountry, FUSportsCity, FUSportsCompetitor, FUSportsCompetitorBase, FUSportsTeamCompetitor, FUSportsPlayerCompetitor, FUSportsPairCompetitor, FUSportsShirtColor, FUSportsSeason, FUSportsRound, FUSportsStage, FUSportsSeasonDetails, FUSportsCompetition, FUSportsVenue, FUSportsOfficial, FUSportsMember, FUSportsMatchMember, FUSportsCoach, FUSportsRelated, FUSportsSocials, FUBranding, FUSportsCompetitionSummary, FUSportsTeamSummary, FUSportsPlayerSummary, FUSportsCountrySummary, FUSportsVenueSummary, FUSportsCoachSummary, FUSportsMatchScore, FUSportsMatchStatus, FUSportsMatchTiming, FUSportsMatchWinner, FUSportsMatch, FUSportsMatchSimple, FUSportsFootballEventType, FUSportsOtherEventType, FUSportsMatchEvent, FUSportsLineupMember, FUSportsCompetitorLineup, FUSportsMatchLineups, FUSportsStatisticEntry, FUSportsCompetitorStatistics, FUSportsMatchStatistics, FUSportsPlayerStatistic, FUSportsPlayerSeasonStatistics, FUSportsCareerTournamentSeason, FUSportsCareerTeam, FUSportsPlayerCareerStatisticsEntry, FUSportsPlayerCareerStatistics, FUSportsPlayerRecentStatistics, FUSportsTeamSeasonStatistics, FUSportsBettingOperatorBranding, FUSportsBettingOperator, FUSportsOddSelection, FUSportsMarketPeriod, FUSportsMarketType, FUSportsOddMarket, FUSportsBettingOperatorOdds, FUSportsMatchOdds, FUSportsCommentaryDetail, FUSportsCommentaryMeta, FUSportsCommentaryItem, FUSportsStandingEntry, FUSportsCompetitorForm, FUSportsStandingLegendItem, FUSportsStandingsMetadata, FUSportsStandings, FUSportsStandingsTable, FUSportsCompetitionStageType, FUSportsCompetitionStandingStat, FUSportsCompetitionStandingEntry, FUSportsCompetitionStandingGroup, FUSportsCompetitionStage, FUSportsCompetitionSeason, FUSportsCompetitionMeta, FUSportsCompetitionDetails, FUSportsSquadMember, FUSportsSquad, FUSportsSearchResultBase, FUSportsTournamentSearchResult, FUSportsPlayerSearchResult, FUSportsTeamSearchResult, FUSportsPresidentSearchResult, FUSportsVenueSearchResult, FUSportsCoachSearchResult, FUSportsSearchResult, FUSportsSearchResults, FUSportsTranslation, FUSportsDisplayAsset, FUSportsSportsSearchResultBase, FUSportsSportsSearchCountry, FUSportsTeamSportsSearchResult, FUSportsCitySportsSearchResult, FUSportsHorseSportsSearchResult, FUSportsPlayerSportsSearchResult, FUSportsCoachSportsSearchResult, FUSportsRefereeSportsSearchResult, FUSportsVenueSportsSearchResult, FUSportsTournamentSportsSearchResult, FUSportsMatchSportsSearchResult, FUSportsCountrySportsSearchResult, FUSportsSportsSearchResult, FUSportsSportsSearchResults, } from "./types/canonical";
35
+ export type { FUSportsCountry, FUSportsCity, FUSportsCompetitor, FUSportsCompetitorBase, FUSportsTeamCompetitor, FUSportsPlayerCompetitor, FUSportsPairCompetitor, FUSportsShirtColor, FUSportsSeason, FUSportsRound, FUSportsStage, FUSportsSeasonDetails, FUSportsCompetition, FUSportsVenue, FUSportsOfficial, FUSportsMember, FUSportsMatchMember, FUSportsCoach, FUSportsRelated, FUSportsSocials, FUBranding, FUSportsCompetitionSummary, FUSportsTeamSummary, FUSportsPlayerSummary, FUSportsCountrySummary, FUSportsVenueSummary, FUSportsCoachSummary, FUSportsMatchScore, FUSportsMatchStatus, FUSportsMatchTiming, FUSportsMatchWinner, FUSportsMatch, FUSportsMatchSimple, FUSportsFootballEventType, FUSportsOtherEventType, FUSportsMatchEvent, FUSportsLineupMember, FUSportsCompetitorLineup, FUSportsMatchLineups, FUSportsStatisticEntry, FUSportsCompetitorStatistics, FUSportsMatchStatistics, FUSportsPlayerStatistic, FUSportsPlayerSeasonStatistics, FUSportsCareerTournamentSeason, FUSportsCareerTeam, FUSportsPlayerCareerStatisticsEntry, FUSportsPlayerCareerStatistics, FUSportsPlayerRecentStatistics, FUSportsTeamSeasonStatistics, FUSportsBettingOperatorBranding, FUSportsBettingOperator, FUSportsOddSelection, FUSportsMarketPeriod, FUSportsMarketType, FUSportsOddMarket, FUSportsBettingOperatorOdds, FUSportsMatchOdds, FUSportsCommentaryDetail, FUSportsCommentaryMeta, FUSportsCommentaryItem, FUSportsStandingEntry, FUSportsCompetitorForm, FUSportsStandingLegendItem, FUSportsStandingsMetadata, FUSportsStandings, FUSportsStandingsTable, FUSportsCompetitionStageType, FUSportsCompetitionStandingStat, FUSportsCompetitionStandingEntry, FUSportsCompetitionStandingGroup, FUSportsCompetitionStage, FUSportsCompetitionSeason, FUSportsCompetitionMeta, FUSportsCompetitionDetails, FUSportsLivescoreSport, FUSportsLivescoreEventStatus, FUSportsLivescoreStatus, FUSportsLivescoreScore, FUSportsLivescoreCompetitor, FUSportsLivescoreEvent, FUSportsLivescoreCompetitionGroup, FUSportsLivescoreMeta, FUSportsLivescore, FUSportsSquadMember, FUSportsSquad, FUSportsSearchResultBase, FUSportsTournamentSearchResult, FUSportsPlayerSearchResult, FUSportsTeamSearchResult, FUSportsPresidentSearchResult, FUSportsVenueSearchResult, FUSportsCoachSearchResult, FUSportsSearchResult, FUSportsSearchResults, FUSportsTranslation, FUSportsDisplayAsset, FUSportsSportsSearchResultBase, FUSportsSportsSearchCountry, FUSportsTeamSportsSearchResult, FUSportsCitySportsSearchResult, FUSportsHorseSportsSearchResult, FUSportsPlayerSportsSearchResult, FUSportsCoachSportsSearchResult, FUSportsRefereeSportsSearchResult, FUSportsVenueSportsSearchResult, FUSportsTournamentSportsSearchResult, FUSportsMatchSportsSearchResult, FUSportsCountrySportsSearchResult, FUSportsSportsSearchResult, FUSportsSportsSearchResults, } from "./types/canonical";
36
36
  export { getActiveSeason, getTeamNextMatch, getTeamPreviousMatch, getTeamUpcomingMatches, getTeamFinishedMatches, getTeamResultsTable, getTeamTopScorers, getTeamTopAssisters, getTeamTopAppearances, getTeamTopMinutesPlayed, getTeamTopCleanSheets, getTeamMostDecorated, aggregatePlayerStatisticsFromMatches, getTopScorersFromMatches, getTopAssistersFromMatches, getMostCardedPlayersFromMatches, getTopGoalContributorsFromMatches, getAllPlayerStatisticsFromMatches, useTopScorersFromMatches, useTopAssistersFromMatches, useMostCardedPlayersFromMatches, useTopGoalContributorsFromMatches, useAllPlayerStatisticsFromMatches, usePlayerStatisticsMap, usePlayerStatistics, } from "./helpers";
37
37
  export type { TeamResultTableResult, TeamResultTableRow, TeamResultTable } from "./helpers";
38
38
  export { calcPercentage, calcAverage, formatStatValue, formatWithAverage, formatAsAverage, formatPossessionPercentage, analyzeMatch, isTeamHome, isTeamAway, isTeamInMatch, isMatchFinished, getTeamScore, getOpponentScore, calculateH2HStats, getRecentH2HMeetings, getTeamHomeAwayStats, getTeamOverUnderStats, getMatchResult, getTeamGoalStats, calculateStreak, getTeamStreaks, getTeamStreaksComparison, streakFilters, getTeamsCommonOpponents, } from "./utilities/stats";
39
39
  export type { MatchAnalysis, MatchResult, MatchFilter, VenueFilter, H2HStats, H2HMatch, HomeVsAwayStats, TeamOverUnderStats, TeamGoalStats, GoalStatRow, StreakData, StreakRow, TeamOpponentResults, TeamsResultsRow, } from "./utilities/stats";
40
40
  export { GOAL_EVENT_TYPES } from "./utilities/stats";
41
- export { initL2, cached, cachedBatch, invalidate } from "./cache";
42
- export type { CacheEntry, EntityCacheConfig, EntityType, L2Store } from "./cache";
41
+ export { initL2, cached, cachedBatch, invalidate, setEntityTTL, getEntityTTL, CACHE_KEY_PREFIX } from "./cache";
42
+ export type { CacheEntry, EntityCacheConfig, EntityType, L2Store, MaybePromise } from "./cache";
43
43
  export { memoryStore } from "./cache/memory-store";
44
44
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "description": "A TypeScript library for fetching and transforming sports data from multiple API providers. Returns clean, canonical types that are provider-agnostic.",
5
5
  "homepage": "https://fansunited.com/",
6
6
  "private": false,
7
- "version": "0.16.0",
7
+ "version": "0.17.0",
8
8
  "type": "module",
9
9
  "sideEffects": false,
10
10
  "module": "./fansunited-data-layer.js",
@@ -48,6 +48,7 @@
48
48
  "fansunited-sdk-esm": "^1.119.2",
49
49
  "fansunited-sports-ui": "^0.0.1",
50
50
  "globals": "^16.5.0",
51
+ "ioredis": "^5.11.1",
51
52
  "prettier": "^3.7.3",
52
53
  "react": "^19.2.0",
53
54
  "react-dom": "^19.2.0",
@@ -12,6 +12,7 @@ export type { FUSportsBettingOperatorBranding, FUSportsBettingOperator, FUSports
12
12
  export type { FUSportsCommentaryDetail, FUSportsCommentaryMeta, FUSportsCommentaryItem } from "./commentary.types";
13
13
  export type { FUSportsStandingEntry, FUSportsCompetitorForm, FUSportsStandingLegendItem, FUSportsStandingsMetadata, FUSportsStandings, FUSportsStandingsTable, } from "./standing.types";
14
14
  export type { FUSportsCompetitionStageType, FUSportsCompetitionStandingStat, FUSportsCompetitionStandingEntry, FUSportsCompetitionStandingGroup, FUSportsCompetitionStage, FUSportsCompetitionSeason, FUSportsCompetitionMeta, FUSportsCompetitionDetails, } from "./sports-competition.types";
15
+ export type { FUSportsLivescoreSport, FUSportsLivescoreEventStatus, FUSportsLivescoreStatus, FUSportsLivescoreScore, FUSportsLivescoreCompetitor, FUSportsLivescoreEvent, FUSportsLivescoreCompetitionGroup, FUSportsLivescoreMeta, FUSportsLivescore, } from "./sports-livescore.types";
15
16
  export type { FUSportsSquadMember, FUSportsSquad } from "./squad.types";
16
17
  export type { FUSportsSearchResultBase, FUSportsTournamentSearchResult, FUSportsPlayerSearchResult, FUSportsTeamSearchResult, FUSportsPresidentSearchResult, FUSportsVenueSearchResult, FUSportsCoachSearchResult, FUSportsSearchResult, FUSportsSearchResults, } from "./search.types";
17
18
  export type { FUSportsTranslation, FUSportsDisplayAsset, FUSportsSportsSearchResultBase, FUSportsSportsSearchCountry, FUSportsTeamSportsSearchResult, FUSportsCitySportsSearchResult, FUSportsHorseSportsSearchResult, FUSportsPlayerSportsSearchResult, FUSportsCoachSportsSearchResult, FUSportsRefereeSportsSearchResult, FUSportsVenueSportsSearchResult, FUSportsTournamentSportsSearchResult, FUSportsMatchSportsSearchResult, FUSportsCountrySportsSearchResult, FUSportsSportsSearchResult, FUSportsSportsSearchResults, } from "./sports-search.types";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/types/canonical/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACR,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,eAAe,EACf,eAAe,EACf,UAAU,EAEV,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACvB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACR,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,GACtB,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG3G,YAAY,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3G,YAAY,EACR,mBAAmB,EACnB,sBAAsB,EACtB,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,8BAA8B,EAC9B,8BAA8B,EAC9B,kBAAkB,EAClB,mCAAmC,EACnC,8BAA8B,EAC9B,8BAA8B,EAC9B,4BAA4B,GAC/B,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACR,+BAA+B,EAC/B,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAGnH,YAAY,EACR,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACR,4BAA4B,EAC5B,+BAA+B,EAC/B,gCAAgC,EAChC,gCAAgC,EAChC,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,GAC7B,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGxE,YAAY,EACR,wBAAwB,EACxB,8BAA8B,EAC9B,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,GACxB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACR,mBAAmB,EACnB,oBAAoB,EACpB,8BAA8B,EAC9B,2BAA2B,EAC3B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,gCAAgC,EAChC,+BAA+B,EAC/B,iCAAiC,EACjC,+BAA+B,EAC/B,oCAAoC,EACpC,+BAA+B,EAC/B,iCAAiC,EACjC,0BAA0B,EAC1B,2BAA2B,GAC9B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/types/canonical/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACR,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,eAAe,EACf,eAAe,EACf,UAAU,EAEV,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACvB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACR,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,GACtB,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAG3G,YAAY,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG3G,YAAY,EACR,mBAAmB,EACnB,sBAAsB,EACtB,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,8BAA8B,EAC9B,8BAA8B,EAC9B,kBAAkB,EAClB,mCAAmC,EACnC,8BAA8B,EAC9B,8BAA8B,EAC9B,4BAA4B,GAC/B,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACR,+BAA+B,EAC/B,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAGnH,YAAY,EACR,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EACjB,sBAAsB,GACzB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACR,4BAA4B,EAC5B,+BAA+B,EAC/B,gCAAgC,EAChC,gCAAgC,EAChC,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,GAC7B,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EACR,sBAAsB,EACtB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,iCAAiC,EACjC,qBAAqB,EACrB,iBAAiB,GACpB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGxE,YAAY,EACR,wBAAwB,EACxB,8BAA8B,EAC9B,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,GACxB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACR,mBAAmB,EACnB,oBAAoB,EACpB,8BAA8B,EAC9B,2BAA2B,EAC3B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,gCAAgC,EAChC,+BAA+B,EAC/B,iCAAiC,EACjC,+BAA+B,EAC/B,oCAAoC,EACpC,+BAA+B,EAC/B,iCAAiC,EACjC,0BAA0B,EAC1B,2BAA2B,GAC9B,MAAM,uBAAuB,CAAC"}