@c15t/backend 2.0.0-rc.4 → 2.0.0-rc.6

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 (327) hide show
  1. package/dist/302.js +473 -0
  2. package/dist/364.js +1140 -0
  3. package/dist/583.js +540 -0
  4. package/dist/cache.cjs +1 -1
  5. package/dist/cache.js +4 -415
  6. package/dist/core.cjs +849 -96
  7. package/dist/core.js +147 -1817
  8. package/dist/db/adapters/drizzle.cjs +1 -1
  9. package/dist/db/adapters/drizzle.js +1 -2
  10. package/dist/db/adapters/kysely.cjs +1 -1
  11. package/dist/db/adapters/kysely.js +1 -2
  12. package/dist/db/adapters/mongo.cjs +1 -1
  13. package/dist/db/adapters/mongo.js +1 -2
  14. package/dist/db/adapters/prisma.cjs +1 -1
  15. package/dist/db/adapters/prisma.js +1 -2
  16. package/dist/db/adapters/typeorm.cjs +1 -1
  17. package/dist/db/adapters/typeorm.js +1 -2
  18. package/dist/db/adapters.cjs +1 -1
  19. package/dist/db/migrator.cjs +1 -1
  20. package/dist/db/schema.cjs +38 -1
  21. package/dist/db/schema.js +33 -2
  22. package/dist/define-config.cjs +1 -1
  23. package/dist/edge.cjs +1106 -0
  24. package/dist/edge.js +190 -0
  25. package/dist/router.cjs +629 -81
  26. package/dist/router.js +1 -1509
  27. package/dist/types/index.cjs +1 -1
  28. package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
  29. package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
  30. package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
  31. package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
  32. package/{dist → dist-types}/cache/gvl-resolver.d.ts +1 -2
  33. package/{dist → dist-types}/cache/index.d.ts +0 -1
  34. package/{dist → dist-types}/cache/keys.d.ts +0 -1
  35. package/{dist → dist-types}/cache/types.d.ts +0 -1
  36. package/{dist → dist-types}/core.d.ts +8 -1
  37. package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
  38. package/{dist → dist-types}/db/registry/consent-policy.d.ts +0 -1
  39. package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
  40. package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
  41. package/{dist → dist-types}/db/registry/index.d.ts +22 -2
  42. package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
  43. package/{dist → dist-types}/db/registry/subject.d.ts +0 -1
  44. package/{dist → dist-types}/db/registry/types.d.ts +1 -2
  45. package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
  46. package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
  47. package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
  48. package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
  49. package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
  50. package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
  51. package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +2 -3
  52. package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
  53. package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -1
  54. package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -1
  55. package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +2 -3
  56. package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +2 -3
  57. package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +2 -3
  58. package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +6 -3
  59. package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +2 -3
  60. package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +432 -17
  61. package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
  62. package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +2 -3
  63. package/{dist → dist-types}/db/schema/index.d.ts +862 -33
  64. package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
  65. package/{dist → dist-types}/define-config.d.ts +0 -1
  66. package/dist-types/edge/index.d.ts +5 -0
  67. package/dist-types/edge/init-handler.d.ts +38 -0
  68. package/dist-types/edge/resolve-consent.d.ts +80 -0
  69. package/dist-types/edge/types.d.ts +13 -0
  70. package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
  71. package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
  72. package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
  73. package/{dist → dist-types}/handlers/init/index.d.ts +4 -5
  74. package/dist-types/handlers/init/policy.d.ts +26 -0
  75. package/dist-types/handlers/init/resolve-init.d.ts +44 -0
  76. package/dist-types/handlers/init/translations.d.ts +48 -0
  77. package/dist-types/handlers/policy/snapshot.d.ts +99 -0
  78. package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
  79. package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
  80. package/{dist → dist-types}/handlers/subject/get.handler.d.ts +0 -1
  81. package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
  82. package/{dist → dist-types}/handlers/subject/list.handler.d.ts +0 -1
  83. package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -1
  84. package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
  85. package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +0 -1
  86. package/{dist → dist-types}/init.d.ts +0 -1
  87. package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
  88. package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
  89. package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
  90. package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
  91. package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +1 -2
  92. package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
  93. package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
  94. package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
  95. package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
  96. package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
  97. package/dist-types/policies/builder.d.ts +127 -0
  98. package/dist-types/policies/defaults.d.ts +2 -0
  99. package/dist-types/policies/matchers.d.ts +3 -0
  100. package/{dist → dist-types}/router.d.ts +0 -1
  101. package/{dist → dist-types}/routes/consent.d.ts +0 -1
  102. package/{src/routes/index.ts → dist-types/routes/index.d.ts} +0 -1
  103. package/{dist → dist-types}/routes/init.d.ts +0 -1
  104. package/{dist → dist-types}/routes/status.d.ts +0 -1
  105. package/{dist → dist-types}/routes/subject.d.ts +0 -1
  106. package/{dist → dist-types}/types/api.d.ts +0 -1
  107. package/{dist → dist-types}/types/index.d.ts +110 -6
  108. package/dist-types/utils/background.d.ts +6 -0
  109. package/{dist → dist-types}/utils/create-telemetry-options.d.ts +0 -1
  110. package/{dist → dist-types}/utils/env.d.ts +0 -1
  111. package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
  112. package/{dist → dist-types}/utils/instrumentation.d.ts +0 -1
  113. package/{dist → dist-types}/utils/logger.d.ts +1 -2
  114. package/{dist → dist-types}/utils/metrics.d.ts +0 -1
  115. package/dist-types/version.d.ts +1 -0
  116. package/docs/README.md +49 -0
  117. package/docs/api/configuration.md +197 -0
  118. package/docs/api/endpoints.md +211 -0
  119. package/docs/guides/caching.md +85 -0
  120. package/docs/guides/database-setup.md +128 -0
  121. package/docs/guides/edge-deployment.md +248 -0
  122. package/docs/guides/framework-integration.md +142 -0
  123. package/docs/guides/iab-tcf.md +89 -0
  124. package/docs/guides/observability.md +96 -0
  125. package/docs/guides/policy-packs.md +396 -0
  126. package/docs/quickstart.md +129 -0
  127. package/package.json +45 -31
  128. package/.turbo/turbo-build.log +0 -49
  129. package/CHANGELOG.md +0 -123
  130. package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
  131. package/dist/cache/adapters/index.d.ts.map +0 -1
  132. package/dist/cache/adapters/memory.d.ts.map +0 -1
  133. package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
  134. package/dist/cache/gvl-resolver.d.ts.map +0 -1
  135. package/dist/cache/index.d.ts.map +0 -1
  136. package/dist/cache/keys.d.ts.map +0 -1
  137. package/dist/cache/types.d.ts.map +0 -1
  138. package/dist/core.d.ts.map +0 -1
  139. package/dist/db/adapters/drizzle.d.ts +0 -2
  140. package/dist/db/adapters/drizzle.d.ts.map +0 -1
  141. package/dist/db/adapters/index.d.ts +0 -2
  142. package/dist/db/adapters/index.d.ts.map +0 -1
  143. package/dist/db/adapters/kysely.d.ts +0 -2
  144. package/dist/db/adapters/kysely.d.ts.map +0 -1
  145. package/dist/db/adapters/mongo.d.ts +0 -2
  146. package/dist/db/adapters/mongo.d.ts.map +0 -1
  147. package/dist/db/adapters/prisma.d.ts +0 -2
  148. package/dist/db/adapters/prisma.d.ts.map +0 -1
  149. package/dist/db/adapters/typeorm.d.ts +0 -2
  150. package/dist/db/adapters/typeorm.d.ts.map +0 -1
  151. package/dist/db/migrator/index.d.ts.map +0 -1
  152. package/dist/db/registry/consent-policy.d.ts.map +0 -1
  153. package/dist/db/registry/consent-purpose.d.ts.map +0 -1
  154. package/dist/db/registry/domain.d.ts.map +0 -1
  155. package/dist/db/registry/index.d.ts.map +0 -1
  156. package/dist/db/registry/subject.d.ts.map +0 -1
  157. package/dist/db/registry/types.d.ts.map +0 -1
  158. package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
  159. package/dist/db/registry/utils.d.ts.map +0 -1
  160. package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
  161. package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
  162. package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
  163. package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
  164. package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
  165. package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
  166. package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
  167. package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
  168. package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
  169. package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
  170. package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
  171. package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
  172. package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
  173. package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
  174. package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
  175. package/dist/db/schema/index.d.ts.map +0 -1
  176. package/dist/db/tenant-scope.d.ts.map +0 -1
  177. package/dist/define-config.d.ts.map +0 -1
  178. package/dist/handlers/consent/check.handler.d.ts.map +0 -1
  179. package/dist/handlers/consent/index.d.ts +0 -12
  180. package/dist/handlers/consent/index.d.ts.map +0 -1
  181. package/dist/handlers/init/geo.d.ts.map +0 -1
  182. package/dist/handlers/init/index.d.ts.map +0 -1
  183. package/dist/handlers/init/translations.d.ts +0 -26
  184. package/dist/handlers/init/translations.d.ts.map +0 -1
  185. package/dist/handlers/status/index.d.ts +0 -7
  186. package/dist/handlers/status/index.d.ts.map +0 -1
  187. package/dist/handlers/status/status.handler.d.ts.map +0 -1
  188. package/dist/handlers/subject/get.handler.d.ts.map +0 -1
  189. package/dist/handlers/subject/index.d.ts +0 -10
  190. package/dist/handlers/subject/index.d.ts.map +0 -1
  191. package/dist/handlers/subject/list.handler.d.ts.map +0 -1
  192. package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
  193. package/dist/handlers/subject/post.handler.d.ts.map +0 -1
  194. package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
  195. package/dist/init.d.ts.map +0 -1
  196. package/dist/middleware/auth/index.d.ts.map +0 -1
  197. package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
  198. package/dist/middleware/cors/cors.d.ts.map +0 -1
  199. package/dist/middleware/cors/index.d.ts +0 -30
  200. package/dist/middleware/cors/index.d.ts.map +0 -1
  201. package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
  202. package/dist/middleware/cors/process-cors.d.ts.map +0 -1
  203. package/dist/middleware/openapi/config.d.ts.map +0 -1
  204. package/dist/middleware/openapi/handlers.d.ts.map +0 -1
  205. package/dist/middleware/openapi/index.d.ts +0 -12
  206. package/dist/middleware/openapi/index.d.ts.map +0 -1
  207. package/dist/middleware/process-ip/index.d.ts.map +0 -1
  208. package/dist/router.d.ts.map +0 -1
  209. package/dist/routes/consent.d.ts.map +0 -1
  210. package/dist/routes/index.d.ts +0 -10
  211. package/dist/routes/index.d.ts.map +0 -1
  212. package/dist/routes/init.d.ts.map +0 -1
  213. package/dist/routes/status.d.ts.map +0 -1
  214. package/dist/routes/subject.d.ts.map +0 -1
  215. package/dist/types/api.d.ts.map +0 -1
  216. package/dist/types/index.d.ts.map +0 -1
  217. package/dist/utils/create-telemetry-options.d.ts.map +0 -1
  218. package/dist/utils/env.d.ts.map +0 -1
  219. package/dist/utils/extract-error-message.d.ts.map +0 -1
  220. package/dist/utils/index.d.ts +0 -4
  221. package/dist/utils/index.d.ts.map +0 -1
  222. package/dist/utils/instrumentation.d.ts.map +0 -1
  223. package/dist/utils/logger.d.ts.map +0 -1
  224. package/dist/utils/metrics.d.ts.map +0 -1
  225. package/dist/version.d.ts +0 -2
  226. package/dist/version.d.ts.map +0 -1
  227. package/knip.json +0 -31
  228. package/rslib.config.ts +0 -93
  229. package/src/cache/adapters/cloudflare-kv.ts +0 -71
  230. package/src/cache/adapters/index.ts +0 -22
  231. package/src/cache/adapters/memory.ts +0 -111
  232. package/src/cache/adapters/upstash-redis.ts +0 -113
  233. package/src/cache/gvl-resolver.ts +0 -289
  234. package/src/cache/index.ts +0 -34
  235. package/src/cache/keys.ts +0 -68
  236. package/src/cache/types.ts +0 -66
  237. package/src/core.ts +0 -369
  238. package/src/db/migrator/index.ts +0 -80
  239. package/src/db/registry/consent-policy.test.ts +0 -451
  240. package/src/db/registry/consent-policy.ts +0 -82
  241. package/src/db/registry/consent-purpose.test.ts +0 -428
  242. package/src/db/registry/consent-purpose.ts +0 -61
  243. package/src/db/registry/domain.test.ts +0 -445
  244. package/src/db/registry/domain.ts +0 -91
  245. package/src/db/registry/index.ts +0 -14
  246. package/src/db/registry/subject.test.ts +0 -371
  247. package/src/db/registry/subject.ts +0 -126
  248. package/src/db/registry/types.ts +0 -10
  249. package/src/db/registry/utils/generate-id.test.ts +0 -216
  250. package/src/db/registry/utils/generate-id.ts +0 -133
  251. package/src/db/registry/utils.ts +0 -133
  252. package/src/db/schema/1.0.0/audit-log.ts +0 -15
  253. package/src/db/schema/1.0.0/consent-policy.ts +0 -14
  254. package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
  255. package/src/db/schema/1.0.0/consent-record.ts +0 -10
  256. package/src/db/schema/1.0.0/consent.ts +0 -20
  257. package/src/db/schema/1.0.0/domain.ts +0 -12
  258. package/src/db/schema/1.0.0/index.ts +0 -48
  259. package/src/db/schema/1.0.0/subject.ts +0 -11
  260. package/src/db/schema/2.0.0/audit-log.ts +0 -18
  261. package/src/db/schema/2.0.0/consent-policy.ts +0 -28
  262. package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
  263. package/src/db/schema/2.0.0/consent.ts +0 -28
  264. package/src/db/schema/2.0.0/domain.ts +0 -12
  265. package/src/db/schema/2.0.0/index.ts +0 -47
  266. package/src/db/schema/2.0.0/subject.ts +0 -13
  267. package/src/db/schema/index.ts +0 -15
  268. package/src/db/tenant-scope.test.ts +0 -747
  269. package/src/db/tenant-scope.ts +0 -103
  270. package/src/define-config.ts +0 -19
  271. package/src/handlers/consent/check.handler.ts +0 -126
  272. package/src/handlers/init/geo.test.ts +0 -317
  273. package/src/handlers/init/geo.ts +0 -195
  274. package/src/handlers/init/index.test.ts +0 -205
  275. package/src/handlers/init/index.ts +0 -114
  276. package/src/handlers/init/translations.test.ts +0 -121
  277. package/src/handlers/init/translations.ts +0 -69
  278. package/src/handlers/status/status.handler.test.ts +0 -155
  279. package/src/handlers/status/status.handler.ts +0 -51
  280. package/src/handlers/subject/get.handler.ts +0 -92
  281. package/src/handlers/subject/list.handler.ts +0 -92
  282. package/src/handlers/subject/patch.handler.ts +0 -119
  283. package/src/handlers/subject/post.handler.test.ts +0 -294
  284. package/src/handlers/subject/post.handler.ts +0 -268
  285. package/src/handlers/utils/consent-enrichment.test.ts +0 -380
  286. package/src/handlers/utils/consent-enrichment.ts +0 -218
  287. package/src/init.test.ts +0 -122
  288. package/src/init.ts +0 -88
  289. package/src/middleware/auth/index.ts +0 -11
  290. package/src/middleware/auth/validate-api-key.test.ts +0 -86
  291. package/src/middleware/auth/validate-api-key.ts +0 -107
  292. package/src/middleware/cors/cors.test.ts +0 -135
  293. package/src/middleware/cors/cors.ts +0 -186
  294. package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
  295. package/src/middleware/cors/is-origin-trusted.ts +0 -130
  296. package/src/middleware/cors/process-cors.ts +0 -91
  297. package/src/middleware/openapi/config.ts +0 -29
  298. package/src/middleware/openapi/handlers.ts +0 -34
  299. package/src/middleware/process-ip/index.test.ts +0 -193
  300. package/src/middleware/process-ip/index.ts +0 -199
  301. package/src/router.ts +0 -15
  302. package/src/routes/consent.ts +0 -52
  303. package/src/routes/init.ts +0 -105
  304. package/src/routes/status.ts +0 -46
  305. package/src/routes/subject.ts +0 -152
  306. package/src/types/api.ts +0 -48
  307. package/src/types/index.ts +0 -391
  308. package/src/utils/create-telemetry-options.test.ts +0 -286
  309. package/src/utils/create-telemetry-options.ts +0 -229
  310. package/src/utils/env.ts +0 -84
  311. package/src/utils/extract-error-message.ts +0 -21
  312. package/src/utils/instrumentation.test.ts +0 -183
  313. package/src/utils/instrumentation.ts +0 -194
  314. package/src/utils/logger.ts +0 -41
  315. package/src/utils/metrics.test.ts +0 -311
  316. package/src/utils/metrics.ts +0 -402
  317. package/src/utils/telemetry-pii.test.ts +0 -323
  318. package/src/version.ts +0 -2
  319. package/tsconfig.json +0 -11
  320. package/vitest.config.ts +0 -28
  321. /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
  322. /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
  323. /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
  324. /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
  325. /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
  326. /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
  327. /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
@@ -1,289 +0,0 @@
1
- /**
2
- * GVL Resolution Service
3
- *
4
- * Resolves Global Vendor List with multi-layer caching:
5
- * 1. Bundled translations (checked first)
6
- * 2. In-memory cache
7
- * 3. External cache (Redis/KV)
8
- * 4. Fetch from gvl.consent.io
9
- *
10
- * @packageDocumentation
11
- */
12
-
13
- import type { GlobalVendorList } from '@c15t/schema/types';
14
- import { withCacheSpan, withExternalSpan } from '~/utils/instrumentation';
15
- import { getMetrics } from '~/utils/metrics';
16
- import { createMemoryCacheAdapter } from './adapters/memory';
17
- import { createGVLCacheKey } from './keys';
18
- import type { CacheAdapter } from './types';
19
- import { GVL_TTL_MS, MEMORY_TTL_MS } from './types';
20
-
21
- /**
22
- * Default GVL endpoint.
23
- */
24
- const GVL_ENDPOINT = 'https://gvl.consent.io';
25
-
26
- /**
27
- * Options for creating a GVL resolver.
28
- *
29
- * @public
30
- */
31
- export interface GVLResolverOptions {
32
- /**
33
- * The application name for cache key prefixing.
34
- */
35
- appName: string;
36
-
37
- /**
38
- * Bundled GVL translations by language code.
39
- * These are checked first before any cache.
40
- */
41
- bundled?: Record<string, GlobalVendorList>;
42
-
43
- /**
44
- * External cache adapter (Redis, KV, etc.).
45
- * If not provided, only in-memory cache is used.
46
- */
47
- cacheAdapter?: CacheAdapter;
48
-
49
- /**
50
- * Vendor IDs to filter when fetching from the GVL endpoint.
51
- * Reduces payload size.
52
- */
53
- vendorIds?: number[];
54
-
55
- /**
56
- * Override the default GVL endpoint.
57
- * @default 'https://gvl.consent.io'
58
- */
59
- endpoint?: string;
60
- }
61
-
62
- /**
63
- * GVL resolver interface.
64
- *
65
- * @public
66
- */
67
- export interface GVLResolver {
68
- /**
69
- * Get a localized GVL for the specified language.
70
- *
71
- * @param language - Language code (e.g., "en", "de")
72
- * @returns The GVL for the language, or null if unavailable
73
- */
74
- get(language: string): Promise<GlobalVendorList | null>;
75
- }
76
-
77
- /**
78
- * In-flight request promises for deduplication.
79
- */
80
- const inflightRequests = new Map<string, Promise<GlobalVendorList | null>>();
81
-
82
- /**
83
- * Fetches GVL from the endpoint with the specified language.
84
- *
85
- * @param language - Language code for Accept-Language header
86
- * @param vendorIds - Optional vendor IDs to filter
87
- * @param endpoint - GVL endpoint URL
88
- * @returns The GVL or null if 204 (non-IAB region)
89
- */
90
- async function fetchGVLWithLanguage(
91
- language: string,
92
- vendorIds?: number[],
93
- endpoint: string = GVL_ENDPOINT
94
- ): Promise<GlobalVendorList | null> {
95
- // Create a stable key for deduplication
96
- const sortedVendorIds = vendorIds ? [...vendorIds].sort((a, b) => a - b) : [];
97
- const dedupeKey = `${endpoint}|${language}|${sortedVendorIds.join(',')}`;
98
-
99
- // Return in-flight request if one exists
100
- const existingRequest = inflightRequests.get(dedupeKey);
101
- if (existingRequest) {
102
- return existingRequest;
103
- }
104
-
105
- // Build URL with vendor IDs filter
106
- const url = new URL(endpoint);
107
- if (sortedVendorIds.length > 0) {
108
- url.searchParams.set('vendorIds', sortedVendorIds.join(','));
109
- }
110
-
111
- // Create and store the in-flight promise
112
- const promise = (async () => {
113
- const fetchStart = Date.now();
114
- try {
115
- const gvl = await withExternalSpan(
116
- { url: url.toString(), method: 'GET' },
117
- async () => {
118
- const response = await fetch(url.toString(), {
119
- headers: {
120
- 'Accept-Language': language,
121
- },
122
- });
123
-
124
- // 204 means non-IAB region - no GVL needed
125
- if (response.status === 204) {
126
- return null;
127
- }
128
-
129
- if (!response.ok) {
130
- throw new Error(
131
- `Failed to fetch GVL: ${response.status} ${response.statusText}`
132
- );
133
- }
134
-
135
- // Use text() then JSON.parse to handle malformed responses (e.g. trailing
136
- // content or BOM) that would break response.json()
137
- const text = await response.text();
138
- const trimmed = text.trim().replace(/^\uFEFF/, ''); // Strip BOM
139
- let parsed: GlobalVendorList;
140
- try {
141
- parsed = JSON.parse(trimmed) as GlobalVendorList;
142
- } catch {
143
- // If response has valid JSON followed by extra content, try parsing
144
- // only the first complete JSON value (find matching braces)
145
- let depth = 0;
146
- let end = -1;
147
- const start = trimmed.indexOf('{');
148
- if (start >= 0) {
149
- for (let i = start; i < trimmed.length; i++) {
150
- const c = trimmed[i];
151
- if (c === '{') depth++;
152
- else if (c === '}') {
153
- depth--;
154
- if (depth === 0) {
155
- end = i + 1;
156
- break;
157
- }
158
- }
159
- }
160
- }
161
- if (end > 0) {
162
- parsed = JSON.parse(trimmed.slice(0, end)) as GlobalVendorList;
163
- } else {
164
- throw new SyntaxError('Invalid GVL response: not valid JSON');
165
- }
166
- }
167
-
168
- // Validate the response has required fields
169
- if (
170
- !parsed.vendorListVersion ||
171
- !parsed.purposes ||
172
- !parsed.vendors
173
- ) {
174
- throw new Error('Invalid GVL response: missing required fields');
175
- }
176
-
177
- return parsed;
178
- }
179
- );
180
-
181
- getMetrics()?.recordGvlFetch(
182
- { language, source: 'fetch', status: 200 },
183
- Date.now() - fetchStart
184
- );
185
-
186
- return gvl;
187
- } catch (error) {
188
- getMetrics()?.recordGvlError({
189
- language,
190
- errorType: error instanceof Error ? error.name : 'UnknownError',
191
- });
192
- throw error;
193
- } finally {
194
- // Clear in-flight request when done
195
- inflightRequests.delete(dedupeKey);
196
- }
197
- })();
198
-
199
- inflightRequests.set(dedupeKey, promise);
200
-
201
- return promise;
202
- }
203
-
204
- /**
205
- * Creates a GVL resolver with multi-layer caching.
206
- *
207
- * Resolution order:
208
- * 1. **Bundled** - Check bundled translations (0ms)
209
- * 2. **In-Memory** - Check worker/process memory cache (0ms)
210
- * 3. **External Cache** - Check Redis/KV if configured (20-40ms)
211
- * 4. **Fetch** - Fetch from gvl.consent.io with Accept-Language (100-300ms)
212
- *
213
- * @param options - Resolver configuration
214
- * @returns A GVL resolver instance
215
- *
216
- * @example
217
- * ```typescript
218
- * const resolver = createGVLResolver({
219
- * appName: 'my-app',
220
- * bundled: { en: enGVL },
221
- * cacheAdapter: redisAdapter,
222
- * vendorIds: [1, 2, 10],
223
- * });
224
- *
225
- * const gvl = await resolver.get('de');
226
- * ```
227
- *
228
- * @public
229
- */
230
- export function createGVLResolver(options: GVLResolverOptions): GVLResolver {
231
- const { appName, bundled, cacheAdapter, vendorIds, endpoint } = options;
232
-
233
- // Create the in-memory cache adapter (always used as first layer)
234
- const memoryCache = createMemoryCacheAdapter();
235
-
236
- return {
237
- async get(language: string): Promise<GlobalVendorList | null> {
238
- const cacheKey = createGVLCacheKey(appName, language, vendorIds);
239
-
240
- // 1. Check bundled languages first (0ms)
241
- if (bundled?.[language]) {
242
- return bundled[language];
243
- }
244
-
245
- // 2. Check in-memory cache (0ms)
246
- const memoryHit = await withCacheSpan('get', 'memory', () =>
247
- memoryCache.get<GlobalVendorList>(cacheKey)
248
- );
249
- if (memoryHit) {
250
- getMetrics()?.recordCacheHit('memory');
251
- return memoryHit;
252
- }
253
- getMetrics()?.recordCacheMiss('memory');
254
-
255
- // 3. Check external cache if configured (20-40ms)
256
- if (cacheAdapter) {
257
- const externalHit = await withCacheSpan('get', 'external', () =>
258
- cacheAdapter.get<GlobalVendorList>(cacheKey)
259
- );
260
- if (externalHit) {
261
- getMetrics()?.recordCacheHit('external');
262
- // Populate memory cache for next request
263
- await withCacheSpan('set', 'memory', () =>
264
- memoryCache.set(cacheKey, externalHit, MEMORY_TTL_MS)
265
- );
266
- return externalHit;
267
- }
268
- getMetrics()?.recordCacheMiss('external');
269
- }
270
-
271
- // 4. Fetch from gvl.consent.io with Accept-Language header (100-300ms)
272
- const gvl = await fetchGVLWithLanguage(language, vendorIds, endpoint);
273
-
274
- if (gvl) {
275
- // Populate both caches
276
- await withCacheSpan('set', 'memory', () =>
277
- memoryCache.set(cacheKey, gvl, MEMORY_TTL_MS)
278
- );
279
- if (cacheAdapter) {
280
- await withCacheSpan('set', 'external', () =>
281
- cacheAdapter.set(cacheKey, gvl, GVL_TTL_MS)
282
- );
283
- }
284
- }
285
-
286
- return gvl;
287
- },
288
- };
289
- }
@@ -1,34 +0,0 @@
1
- /**
2
- * Cache Module
3
- *
4
- * Multi-layer caching system with pluggable adapters for GVL and other data.
5
- *
6
- * @packageDocumentation
7
- */
8
-
9
- // Adapters
10
- export {
11
- clearMemoryCache,
12
- // Cloudflare KV
13
- createCloudflareKVAdapter,
14
- // Memory
15
- createMemoryCacheAdapter,
16
- // Upstash Redis
17
- createUpstashRedisAdapter,
18
- createUpstashRedisAdapterFromClient,
19
- getMemoryCacheSize,
20
- type KVNamespace,
21
- type UpstashRedisAdapterOptions,
22
- } from './adapters';
23
- // GVL Resolver
24
- export {
25
- createGVLResolver,
26
- type GVLResolver,
27
- type GVLResolverOptions,
28
- } from './gvl-resolver';
29
-
30
- // Cache Key Utilities
31
- export { createCacheKey, createGVLCacheKey } from './keys';
32
- // Types
33
- export type { CacheAdapter } from './types';
34
- export { GVL_TTL_MS, MEMORY_TTL_MS } from './types';
package/src/cache/keys.ts DELETED
@@ -1,68 +0,0 @@
1
- /**
2
- * Cache Key Utilities
3
- *
4
- * Functions for generating consistent cache keys with app name prefixing.
5
- *
6
- * @packageDocumentation
7
- */
8
-
9
- /**
10
- * Create a GVL cache key.
11
- *
12
- * Format: `{appName}:gvl:{language}:{sortedVendorIds}`
13
- *
14
- * @param appName - The application name for key prefixing
15
- * @param language - The language code (e.g., "en", "de")
16
- * @param vendorIds - Optional array of vendor IDs to include in the key
17
- * @returns A unique cache key for the GVL configuration
18
- *
19
- * @example
20
- * ```typescript
21
- * // All vendors
22
- * createGVLCacheKey('my-app', 'en');
23
- * // => 'my-app:gvl:en:all'
24
- *
25
- * // Specific vendors
26
- * createGVLCacheKey('my-app', 'de', [1, 10, 2]);
27
- * // => 'my-app:gvl:de:1,2,10'
28
- * ```
29
- *
30
- * @public
31
- */
32
- export function createGVLCacheKey(
33
- appName: string,
34
- language: string,
35
- vendorIds?: number[]
36
- ): string {
37
- const sortedIds = vendorIds
38
- ? [...vendorIds].sort((a, b) => a - b).join(',')
39
- : 'all';
40
- return `${appName}:gvl:${language}:${sortedIds}`;
41
- }
42
-
43
- /**
44
- * Create a generic cache key with namespace and parts.
45
- *
46
- * Format: `{appName}:{namespace}:{part1}:{part2}:...`
47
- *
48
- * @param appName - The application name for key prefixing
49
- * @param namespace - The cache namespace (e.g., "gvl", "translations")
50
- * @param parts - Additional key parts
51
- * @returns A namespaced cache key
52
- *
53
- * @example
54
- * ```typescript
55
- * createCacheKey('my-app', 'translations', 'en', 'banner');
56
- * // => 'my-app:translations:en:banner'
57
- * ```
58
- *
59
- * @public
60
- */
61
- export function createCacheKey(
62
- appName: string,
63
- namespace: string,
64
- ...parts: (string | number)[]
65
- ): string {
66
- const allParts = [appName, namespace, ...parts];
67
- return allParts.join(':');
68
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Cache Adapter Types
3
- *
4
- * Generic cache adapter interface for pluggable caching implementations.
5
- * Supports in-memory, Redis, Cloudflare KV, and custom adapters.
6
- *
7
- * @packageDocumentation
8
- */
9
-
10
- /**
11
- * Generic cache adapter interface.
12
- *
13
- * Implementations should handle serialization/deserialization internally.
14
- * All methods are async to support both sync (memory) and async (Redis/KV) backends.
15
- *
16
- * @public
17
- */
18
- export interface CacheAdapter {
19
- /**
20
- * Get a value from the cache.
21
- *
22
- * @param key - Cache key
23
- * @returns The cached value, or null if not found or expired
24
- */
25
- get<T>(key: string): Promise<T | null>;
26
-
27
- /**
28
- * Set a value in the cache.
29
- *
30
- * @param key - Cache key
31
- * @param value - Value to cache
32
- * @param ttlMs - Time to live in milliseconds (optional)
33
- */
34
- set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
35
-
36
- /**
37
- * Delete a value from the cache.
38
- *
39
- * @param key - Cache key
40
- */
41
- delete(key: string): Promise<void>;
42
-
43
- /**
44
- * Check if a key exists in the cache.
45
- *
46
- * @param key - Cache key
47
- * @returns True if the key exists and is not expired
48
- */
49
- has(key: string): Promise<boolean>;
50
- }
51
-
52
- /**
53
- * Default TTL for GVL cache entries (3 days).
54
- * Matches the typical GVL update frequency.
55
- *
56
- * @public
57
- */
58
- export const GVL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days
59
-
60
- /**
61
- * Default TTL for in-memory cache entries (5 minutes).
62
- * Shorter TTL to handle worker restarts and keep memory usage low.
63
- *
64
- * @public
65
- */
66
- export const MEMORY_TTL_MS = 5 * 60 * 1000; // 5 minutes