@c15t/backend 2.0.0-rc.0 → 2.0.0-rc.10

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 (336) hide show
  1. package/README.md +3 -3
  2. package/dist/302.js +473 -0
  3. package/dist/583.js +540 -0
  4. package/dist/915.js +1771 -0
  5. package/dist/cache.cjs +5 -5
  6. package/dist/cache.js +4 -415
  7. package/dist/core.cjs +1356 -120
  8. package/dist/core.js +163 -1981
  9. package/dist/db/adapters/drizzle.cjs +1 -1
  10. package/dist/db/adapters/drizzle.js +1 -2
  11. package/dist/db/adapters/kysely.cjs +1 -1
  12. package/dist/db/adapters/kysely.js +1 -2
  13. package/dist/db/adapters/mongo.cjs +1 -1
  14. package/dist/db/adapters/mongo.js +1 -2
  15. package/dist/db/adapters/prisma.cjs +1 -1
  16. package/dist/db/adapters/prisma.js +1 -2
  17. package/dist/db/adapters/typeorm.cjs +1 -1
  18. package/dist/db/adapters/typeorm.js +1 -2
  19. package/dist/db/adapters.cjs +1 -1
  20. package/dist/db/migrator.cjs +1 -1
  21. package/dist/db/schema.cjs +43 -3
  22. package/dist/db/schema.js +35 -4
  23. package/dist/define-config.cjs +1 -1
  24. package/dist/edge.cjs +1106 -0
  25. package/dist/edge.js +190 -0
  26. package/dist/router.cjs +885 -123
  27. package/dist/router.js +1 -1507
  28. package/dist/{types.cjs → types/index.cjs} +1 -1
  29. package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
  30. package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
  31. package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
  32. package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
  33. package/{dist → dist-types}/cache/gvl-resolver.d.ts +0 -1
  34. package/{dist → dist-types}/cache/index.d.ts +0 -1
  35. package/{dist → dist-types}/cache/keys.d.ts +0 -1
  36. package/{dist → dist-types}/cache/types.d.ts +0 -1
  37. package/{dist → dist-types}/core.d.ts +8 -1
  38. package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
  39. package/dist-types/db/registry/consent-policy.d.ts +78 -0
  40. package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
  41. package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
  42. package/dist-types/db/registry/index.d.ts +118 -0
  43. package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
  44. package/{dist → dist-types}/db/registry/subject.d.ts +0 -2
  45. package/{dist → dist-types}/db/registry/types.d.ts +1 -1
  46. package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
  47. package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
  48. package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
  49. package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
  50. package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
  51. package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
  52. package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
  53. package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
  54. package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -32
  55. package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -2
  56. package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
  57. package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +3 -3
  58. package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
  59. package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +7 -2
  60. package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
  61. package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +455 -28
  62. package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
  63. package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -3
  64. package/{dist → dist-types}/db/schema/index.d.ts +908 -86
  65. package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
  66. package/dist-types/define-config.d.ts +17 -0
  67. package/dist-types/edge/index.d.ts +5 -0
  68. package/dist-types/edge/init-handler.d.ts +40 -0
  69. package/dist-types/edge/resolve-consent.d.ts +80 -0
  70. package/dist-types/edge/types.d.ts +13 -0
  71. package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
  72. package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
  73. package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
  74. package/{dist → dist-types}/handlers/init/index.d.ts +2 -3
  75. package/dist-types/handlers/init/policy.d.ts +26 -0
  76. package/dist-types/handlers/init/resolve-init.d.ts +44 -0
  77. package/dist-types/handlers/init/translations.d.ts +48 -0
  78. package/dist-types/handlers/legal-document/current.handler.d.ts +11 -0
  79. package/dist-types/handlers/legal-document/snapshot.d.ts +39 -0
  80. package/dist-types/handlers/policy/snapshot.d.ts +99 -0
  81. package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
  82. package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
  83. package/{dist → dist-types}/handlers/subject/get.handler.d.ts +3 -2
  84. package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
  85. package/{dist → dist-types}/handlers/subject/list.handler.d.ts +3 -2
  86. package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -2
  87. package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
  88. package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +3 -1
  89. package/{dist → dist-types}/init.d.ts +4 -7
  90. package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
  91. package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
  92. package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
  93. package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
  94. package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +0 -1
  95. package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
  96. package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
  97. package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
  98. package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
  99. package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
  100. package/dist-types/policies/builder.d.ts +127 -0
  101. package/dist-types/policies/defaults.d.ts +2 -0
  102. package/dist-types/policies/matchers.d.ts +3 -0
  103. package/{dist → dist-types}/router.d.ts +0 -1
  104. package/{dist → dist-types}/routes/consent.d.ts +0 -1
  105. package/{dist → dist-types}/routes/index.d.ts +1 -1
  106. package/{dist → dist-types}/routes/init.d.ts +0 -1
  107. package/dist-types/routes/legal-document.d.ts +7 -0
  108. package/{dist → dist-types}/routes/status.d.ts +0 -1
  109. package/{dist → dist-types}/routes/subject.d.ts +0 -1
  110. package/{dist → dist-types}/types/api.d.ts +0 -1
  111. package/dist-types/types/index.d.ts +464 -0
  112. package/dist-types/utils/background.d.ts +6 -0
  113. package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
  114. package/{dist → dist-types}/utils/env.d.ts +0 -1
  115. package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
  116. package/{dist → dist-types}/utils/instrumentation.d.ts +2 -3
  117. package/{dist → dist-types}/utils/logger.d.ts +0 -1
  118. package/{dist → dist-types}/utils/metrics.d.ts +0 -1
  119. package/dist-types/version.d.ts +1 -0
  120. package/docs/README.md +49 -0
  121. package/docs/api/configuration.md +208 -0
  122. package/docs/api/endpoints.md +211 -0
  123. package/docs/guides/caching.md +85 -0
  124. package/docs/guides/database-setup.md +128 -0
  125. package/docs/guides/edge-deployment.md +251 -0
  126. package/docs/guides/framework-integration.md +142 -0
  127. package/docs/guides/iab-tcf.md +89 -0
  128. package/docs/guides/observability.md +96 -0
  129. package/docs/guides/policy-packs.md +396 -0
  130. package/docs/quickstart.md +129 -0
  131. package/package.json +53 -39
  132. package/.turbo/turbo-build.log +0 -49
  133. package/CHANGELOG.md +0 -89
  134. package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
  135. package/dist/cache/adapters/index.d.ts.map +0 -1
  136. package/dist/cache/adapters/memory.d.ts.map +0 -1
  137. package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
  138. package/dist/cache/gvl-resolver.d.ts.map +0 -1
  139. package/dist/cache/index.d.ts.map +0 -1
  140. package/dist/cache/keys.d.ts.map +0 -1
  141. package/dist/cache/types.d.ts.map +0 -1
  142. package/dist/core.d.ts.map +0 -1
  143. package/dist/db/adapters/drizzle.d.ts +0 -2
  144. package/dist/db/adapters/drizzle.d.ts.map +0 -1
  145. package/dist/db/adapters/index.d.ts +0 -2
  146. package/dist/db/adapters/index.d.ts.map +0 -1
  147. package/dist/db/adapters/kysely.d.ts +0 -2
  148. package/dist/db/adapters/kysely.d.ts.map +0 -1
  149. package/dist/db/adapters/mongo.d.ts +0 -2
  150. package/dist/db/adapters/mongo.d.ts.map +0 -1
  151. package/dist/db/adapters/prisma.d.ts +0 -2
  152. package/dist/db/adapters/prisma.d.ts.map +0 -1
  153. package/dist/db/adapters/typeorm.d.ts +0 -2
  154. package/dist/db/adapters/typeorm.d.ts.map +0 -1
  155. package/dist/db/migrator/index.d.ts.map +0 -1
  156. package/dist/db/registry/consent-policy.d.ts +0 -23
  157. package/dist/db/registry/consent-policy.d.ts.map +0 -1
  158. package/dist/db/registry/consent-purpose.d.ts.map +0 -1
  159. package/dist/db/registry/domain.d.ts.map +0 -1
  160. package/dist/db/registry/index.d.ts +0 -57
  161. package/dist/db/registry/index.d.ts.map +0 -1
  162. package/dist/db/registry/subject.d.ts.map +0 -1
  163. package/dist/db/registry/types.d.ts.map +0 -1
  164. package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
  165. package/dist/db/registry/utils.d.ts.map +0 -1
  166. package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
  167. package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
  168. package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
  169. package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
  170. package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
  171. package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
  172. package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
  173. package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
  174. package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
  175. package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
  176. package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
  177. package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
  178. package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
  179. package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
  180. package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
  181. package/dist/db/schema/index.d.ts.map +0 -1
  182. package/dist/db/tenant-scope.d.ts.map +0 -1
  183. package/dist/define-config.d.ts +0 -5
  184. package/dist/define-config.d.ts.map +0 -1
  185. package/dist/handlers/consent/check.handler.d.ts.map +0 -1
  186. package/dist/handlers/consent/index.d.ts +0 -12
  187. package/dist/handlers/consent/index.d.ts.map +0 -1
  188. package/dist/handlers/init/geo.d.ts.map +0 -1
  189. package/dist/handlers/init/index.d.ts.map +0 -1
  190. package/dist/handlers/init/translations.d.ts +0 -28
  191. package/dist/handlers/init/translations.d.ts.map +0 -1
  192. package/dist/handlers/status/index.d.ts +0 -7
  193. package/dist/handlers/status/index.d.ts.map +0 -1
  194. package/dist/handlers/status/status.handler.d.ts.map +0 -1
  195. package/dist/handlers/subject/get.handler.d.ts.map +0 -1
  196. package/dist/handlers/subject/index.d.ts +0 -10
  197. package/dist/handlers/subject/index.d.ts.map +0 -1
  198. package/dist/handlers/subject/list.handler.d.ts.map +0 -1
  199. package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
  200. package/dist/handlers/subject/post.handler.d.ts.map +0 -1
  201. package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
  202. package/dist/init.d.ts.map +0 -1
  203. package/dist/middleware/auth/index.d.ts.map +0 -1
  204. package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
  205. package/dist/middleware/cors/cors.d.ts.map +0 -1
  206. package/dist/middleware/cors/index.d.ts +0 -30
  207. package/dist/middleware/cors/index.d.ts.map +0 -1
  208. package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
  209. package/dist/middleware/cors/process-cors.d.ts.map +0 -1
  210. package/dist/middleware/openapi/config.d.ts.map +0 -1
  211. package/dist/middleware/openapi/handlers.d.ts.map +0 -1
  212. package/dist/middleware/openapi/index.d.ts +0 -12
  213. package/dist/middleware/openapi/index.d.ts.map +0 -1
  214. package/dist/middleware/process-ip/index.d.ts.map +0 -1
  215. package/dist/router.d.ts.map +0 -1
  216. package/dist/routes/consent.d.ts.map +0 -1
  217. package/dist/routes/index.d.ts.map +0 -1
  218. package/dist/routes/init.d.ts.map +0 -1
  219. package/dist/routes/status.d.ts.map +0 -1
  220. package/dist/routes/subject.d.ts.map +0 -1
  221. package/dist/types/api.d.ts.map +0 -1
  222. package/dist/types/index.d.ts +0 -255
  223. package/dist/types/index.d.ts.map +0 -1
  224. package/dist/utils/create-telemetry-options.d.ts.map +0 -1
  225. package/dist/utils/env.d.ts.map +0 -1
  226. package/dist/utils/extract-error-message.d.ts.map +0 -1
  227. package/dist/utils/index.d.ts +0 -4
  228. package/dist/utils/index.d.ts.map +0 -1
  229. package/dist/utils/instrumentation.d.ts.map +0 -1
  230. package/dist/utils/logger.d.ts.map +0 -1
  231. package/dist/utils/metrics.d.ts.map +0 -1
  232. package/dist/version.d.ts +0 -2
  233. package/dist/version.d.ts.map +0 -1
  234. package/knip.json +0 -31
  235. package/rslib.config.ts +0 -93
  236. package/src/cache/adapters/cloudflare-kv.ts +0 -71
  237. package/src/cache/adapters/index.ts +0 -22
  238. package/src/cache/adapters/memory.ts +0 -111
  239. package/src/cache/adapters/upstash-redis.ts +0 -113
  240. package/src/cache/gvl-resolver.ts +0 -289
  241. package/src/cache/index.ts +0 -34
  242. package/src/cache/keys.ts +0 -68
  243. package/src/cache/types.ts +0 -66
  244. package/src/core.ts +0 -368
  245. package/src/db/migrator/index.ts +0 -80
  246. package/src/db/registry/consent-policy.test.ts +0 -451
  247. package/src/db/registry/consent-policy.ts +0 -82
  248. package/src/db/registry/consent-purpose.test.ts +0 -428
  249. package/src/db/registry/consent-purpose.ts +0 -61
  250. package/src/db/registry/domain.test.ts +0 -445
  251. package/src/db/registry/domain.ts +0 -91
  252. package/src/db/registry/index.ts +0 -14
  253. package/src/db/registry/subject.test.ts +0 -388
  254. package/src/db/registry/subject.ts +0 -129
  255. package/src/db/registry/types.ts +0 -10
  256. package/src/db/registry/utils/generate-id.test.ts +0 -216
  257. package/src/db/registry/utils/generate-id.ts +0 -133
  258. package/src/db/registry/utils.ts +0 -133
  259. package/src/db/schema/1.0.0/audit-log.ts +0 -15
  260. package/src/db/schema/1.0.0/consent-policy.ts +0 -14
  261. package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
  262. package/src/db/schema/1.0.0/consent-record.ts +0 -10
  263. package/src/db/schema/1.0.0/consent.ts +0 -20
  264. package/src/db/schema/1.0.0/domain.ts +0 -12
  265. package/src/db/schema/1.0.0/index.ts +0 -48
  266. package/src/db/schema/1.0.0/subject.ts +0 -12
  267. package/src/db/schema/2.0.0/audit-log.ts +0 -18
  268. package/src/db/schema/2.0.0/consent-policy.ts +0 -28
  269. package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
  270. package/src/db/schema/2.0.0/consent.ts +0 -26
  271. package/src/db/schema/2.0.0/domain.ts +0 -12
  272. package/src/db/schema/2.0.0/index.ts +0 -47
  273. package/src/db/schema/2.0.0/subject.ts +0 -14
  274. package/src/db/schema/index.ts +0 -15
  275. package/src/db/tenant-scope.test.ts +0 -750
  276. package/src/db/tenant-scope.ts +0 -103
  277. package/src/define-config.ts +0 -5
  278. package/src/handlers/consent/check.handler.ts +0 -126
  279. package/src/handlers/init/geo.test.ts +0 -317
  280. package/src/handlers/init/geo.ts +0 -195
  281. package/src/handlers/init/index.test.ts +0 -205
  282. package/src/handlers/init/index.ts +0 -114
  283. package/src/handlers/init/translations.test.ts +0 -121
  284. package/src/handlers/init/translations.ts +0 -72
  285. package/src/handlers/status/status.handler.test.ts +0 -155
  286. package/src/handlers/status/status.handler.ts +0 -51
  287. package/src/handlers/subject/get.handler.ts +0 -93
  288. package/src/handlers/subject/list.handler.ts +0 -93
  289. package/src/handlers/subject/patch.handler.ts +0 -122
  290. package/src/handlers/subject/post.handler.test.ts +0 -294
  291. package/src/handlers/subject/post.handler.ts +0 -254
  292. package/src/handlers/utils/consent-enrichment.test.ts +0 -380
  293. package/src/handlers/utils/consent-enrichment.ts +0 -218
  294. package/src/init.test.ts +0 -126
  295. package/src/init.ts +0 -87
  296. package/src/middleware/auth/index.ts +0 -11
  297. package/src/middleware/auth/validate-api-key.test.ts +0 -86
  298. package/src/middleware/auth/validate-api-key.ts +0 -107
  299. package/src/middleware/cors/cors.test.ts +0 -135
  300. package/src/middleware/cors/cors.ts +0 -186
  301. package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
  302. package/src/middleware/cors/is-origin-trusted.ts +0 -130
  303. package/src/middleware/cors/process-cors.ts +0 -91
  304. package/src/middleware/openapi/config.ts +0 -29
  305. package/src/middleware/openapi/handlers.ts +0 -34
  306. package/src/middleware/process-ip/index.test.ts +0 -195
  307. package/src/middleware/process-ip/index.ts +0 -199
  308. package/src/router.ts +0 -15
  309. package/src/routes/consent.ts +0 -52
  310. package/src/routes/index.ts +0 -10
  311. package/src/routes/init.ts +0 -102
  312. package/src/routes/status.ts +0 -46
  313. package/src/routes/subject.ts +0 -152
  314. package/src/types/api.ts +0 -48
  315. package/src/types/index.ts +0 -288
  316. package/src/utils/create-telemetry-options.test.ts +0 -302
  317. package/src/utils/create-telemetry-options.ts +0 -229
  318. package/src/utils/env.ts +0 -84
  319. package/src/utils/extract-error-message.ts +0 -21
  320. package/src/utils/instrumentation.test.ts +0 -185
  321. package/src/utils/instrumentation.ts +0 -196
  322. package/src/utils/logger.ts +0 -41
  323. package/src/utils/metrics.test.ts +0 -323
  324. package/src/utils/metrics.ts +0 -402
  325. package/src/utils/telemetry-pii.test.ts +0 -325
  326. package/src/version.ts +0 -2
  327. package/tsconfig.json +0 -11
  328. package/vitest.config.ts +0 -28
  329. /package/dist/{types.js → types/index.js} +0 -0
  330. /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
  331. /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
  332. /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
  333. /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
  334. /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
  335. /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
  336. /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
package/dist/583.js ADDED
@@ -0,0 +1,540 @@
1
+ import { inspectPolicies, resolvePolicyDecision, resolvePolicySync, validatePolicyI18nConfig } from "@c15t/schema/types";
2
+ import { deepMergeTranslations, selectLanguage } from "@c15t/translations";
3
+ import { baseTranslations } from "@c15t/translations/all";
4
+ import { SignJWT, errors, jwtVerify } from "jose";
5
+ import { createGVLResolver, getMetrics } from "./302.js";
6
+ const DEFAULT_PROFILE = 'default';
7
+ const warnedKeys = new Set();
8
+ function isSupportedBaseLanguage(lang) {
9
+ return lang in baseTranslations;
10
+ }
11
+ function warnOnce(logger, key, message, metadata) {
12
+ if (!logger || warnedKeys.has(key)) return;
13
+ warnedKeys.add(key);
14
+ logger.warn(message, metadata);
15
+ }
16
+ function normalizeLanguage(value) {
17
+ if (!value) return;
18
+ const normalized = value.split(',')[0]?.split(';')[0]?.trim().toLowerCase();
19
+ if (!normalized) return;
20
+ return normalized.split('-')[0] ?? void 0;
21
+ }
22
+ function normalizeProfiles(params) {
23
+ const profiles = params.i18n?.messages;
24
+ const legacy = params.customTranslations;
25
+ if (profiles && Object.keys(profiles).length > 0) {
26
+ if (legacy && Object.keys(legacy).length > 0) warnOnce(params.logger, 'i18n.customTranslations.ignored', '`customTranslations` is deprecated and ignored when `i18n.messages` is configured.');
27
+ return profiles;
28
+ }
29
+ if (legacy && Object.keys(legacy).length > 0) {
30
+ warnOnce(params.logger, 'i18n.customTranslations.deprecated', '`customTranslations` is deprecated. Use `i18n.messages` instead.');
31
+ return {
32
+ [DEFAULT_PROFILE]: {
33
+ translations: legacy
34
+ }
35
+ };
36
+ }
37
+ return {};
38
+ }
39
+ function buildCandidates(input) {
40
+ const raw = [
41
+ {
42
+ language: input.language,
43
+ reason: 'profile_language'
44
+ },
45
+ {
46
+ language: input.fallbackLanguage,
47
+ reason: 'profile_fallback'
48
+ }
49
+ ];
50
+ const dedupe = new Set();
51
+ return raw.filter((candidate)=>{
52
+ const key = candidate.language;
53
+ if (dedupe.has(key)) return false;
54
+ dedupe.add(key);
55
+ return true;
56
+ });
57
+ }
58
+ function getProfileLanguages(profiles, profile) {
59
+ return Object.keys(profiles[profile]?.translations ?? {}).sort();
60
+ }
61
+ function getSelectableLanguages(input) {
62
+ return getProfileLanguages(input.profiles, input.profile);
63
+ }
64
+ function resolveFallbackLanguage(input) {
65
+ const configuredFallbackLanguage = normalizeLanguage(input.profile?.fallbackLanguage) ?? 'en';
66
+ const profileLanguages = Object.keys(input.profile?.translations ?? {}).sort();
67
+ if (profileLanguages.includes(configuredFallbackLanguage)) return configuredFallbackLanguage;
68
+ if (profileLanguages.includes('en')) return 'en';
69
+ return profileLanguages[0] ?? configuredFallbackLanguage;
70
+ }
71
+ function resolveActiveProfile(input) {
72
+ const requestedProfile = input.policyProfile ?? input.defaultProfile;
73
+ if (input.profiles[requestedProfile]) return requestedProfile;
74
+ if (input.policyProfile) warnOnce(input.logger, `i18n.profile.missing:${requestedProfile}`, `Policy i18n profile '${requestedProfile}' does not exist. Falling back to default profile '${input.defaultProfile}'.`);
75
+ return input.defaultProfile;
76
+ }
77
+ function validateMessages(options) {
78
+ return validatePolicyI18nConfig({
79
+ customTranslations: options.customTranslations,
80
+ i18n: options.i18n,
81
+ policies: options.policies
82
+ });
83
+ }
84
+ function getTranslationsData(acceptLanguage, customTranslations, options) {
85
+ const profiles = normalizeProfiles({
86
+ customTranslations,
87
+ i18n: options?.i18n,
88
+ logger: options?.logger
89
+ });
90
+ const defaultProfile = options?.i18n?.defaultProfile ?? DEFAULT_PROFILE;
91
+ const profile = resolveActiveProfile({
92
+ profiles,
93
+ defaultProfile,
94
+ policyProfile: options?.policyI18n?.messageProfile,
95
+ logger: options?.logger
96
+ });
97
+ const configuredLanguages = Object.keys(profiles).length > 0 ? getSelectableLanguages({
98
+ profiles,
99
+ profile
100
+ }) : Object.keys(baseTranslations);
101
+ const fallbackLanguage = Object.keys(profiles).length > 0 ? resolveFallbackLanguage({
102
+ profile: profiles[profile]
103
+ }) : 'en';
104
+ const policyLanguage = normalizeLanguage(options?.policyI18n?.language);
105
+ const requestedLanguage = policyLanguage ?? selectLanguage(configuredLanguages, {
106
+ header: acceptLanguage,
107
+ fallback: fallbackLanguage
108
+ });
109
+ const candidates = buildCandidates({
110
+ language: requestedLanguage,
111
+ fallbackLanguage
112
+ });
113
+ const selectedCandidate = candidates.find((candidate)=>!!profiles[profile]?.translations[candidate.language]);
114
+ if (selectedCandidate && 'profile_language' !== selectedCandidate.reason) warnOnce(options?.logger, `i18n.fallback:${profile}:${requestedLanguage}:${selectedCandidate.language}`, `Policy translation fallback used (${selectedCandidate.reason}).`, {
115
+ requestedProfile: profile,
116
+ requestedLanguage,
117
+ resolvedProfile: profile,
118
+ resolvedLanguage: selectedCandidate.language
119
+ });
120
+ let language = selectedCandidate?.language ?? requestedLanguage;
121
+ if (!selectedCandidate && !isSupportedBaseLanguage(language)) {
122
+ warnOnce(options?.logger, `i18n.base-fallback:${language}`, `No translation found for '${language}'. Falling back to base English translations.`);
123
+ language = 'en';
124
+ }
125
+ const base = isSupportedBaseLanguage(language) ? baseTranslations[language] : baseTranslations.en;
126
+ const custom = selectedCandidate ? profiles[profile]?.translations[selectedCandidate.language] : void 0;
127
+ const translations = custom ? deepMergeTranslations(base, custom) : base;
128
+ return {
129
+ translations: translations,
130
+ language
131
+ };
132
+ }
133
+ function policy_inspectPolicies(policies, options) {
134
+ return inspectPolicies(policies, options);
135
+ }
136
+ async function policy_resolvePolicyDecision(params) {
137
+ return resolvePolicyDecision({
138
+ policies: params.policies,
139
+ countryCode: params.countryCode,
140
+ regionCode: params.regionCode,
141
+ jurisdiction: params.jurisdiction,
142
+ iabEnabled: params.iabEnabled
143
+ });
144
+ }
145
+ function policy_resolvePolicySync(params) {
146
+ return resolvePolicySync({
147
+ policies: params.policies,
148
+ countryCode: params.countryCode,
149
+ regionCode: params.regionCode,
150
+ jurisdiction: params.jurisdiction,
151
+ iabEnabled: params.iabEnabled
152
+ });
153
+ }
154
+ const POLICY_SNAPSHOT_JWT_HEADER = {
155
+ alg: 'HS256',
156
+ typ: 'JWT'
157
+ };
158
+ const DEFAULT_POLICY_SNAPSHOT_ISSUER = 'c15t';
159
+ const DEFAULT_POLICY_SNAPSHOT_AUDIENCE = 'c15t-policy-snapshot';
160
+ function resolveSnapshotIssuer(options) {
161
+ return options?.issuer?.trim() || DEFAULT_POLICY_SNAPSHOT_ISSUER;
162
+ }
163
+ function resolveSnapshotAudience(params) {
164
+ const configuredAudience = params.options?.audience?.trim();
165
+ if (configuredAudience) return configuredAudience;
166
+ return params.tenantId ? `${DEFAULT_POLICY_SNAPSHOT_AUDIENCE}:${params.tenantId}` : DEFAULT_POLICY_SNAPSHOT_AUDIENCE;
167
+ }
168
+ function getSigningKey(secret) {
169
+ return new TextEncoder().encode(secret);
170
+ }
171
+ function isPolicySnapshotPayload(payload) {
172
+ return 'string' == typeof payload.policyId && 'string' == typeof payload.fingerprint && 'string' == typeof payload.matchedBy && 'string' == typeof payload.jurisdiction && 'string' == typeof payload.model && 'string' == typeof payload.iss && 'string' == typeof payload.aud && 'string' == typeof payload.sub && 'number' == typeof payload.iat && 'number' == typeof payload.exp;
173
+ }
174
+ async function createPolicySnapshotToken(params) {
175
+ const { options } = params;
176
+ if (!options?.signingKey) return;
177
+ const iat = Math.floor(Date.now() / 1000);
178
+ const ttlSeconds = options.ttlSeconds ?? 1800;
179
+ const exp = iat + ttlSeconds;
180
+ const iss = resolveSnapshotIssuer(options);
181
+ const aud = resolveSnapshotAudience({
182
+ options,
183
+ tenantId: params.tenantId
184
+ });
185
+ const payload = {
186
+ iss,
187
+ aud,
188
+ sub: params.policyId,
189
+ tenantId: params.tenantId,
190
+ policyId: params.policyId,
191
+ fingerprint: params.fingerprint,
192
+ matchedBy: params.matchedBy,
193
+ country: params.country,
194
+ region: params.region,
195
+ jurisdiction: params.jurisdiction,
196
+ language: params.language,
197
+ model: params.model,
198
+ policyI18n: params.policyI18n,
199
+ expiryDays: params.expiryDays,
200
+ scopeMode: params.scopeMode,
201
+ uiMode: params.uiMode,
202
+ bannerUi: params.bannerUi,
203
+ dialogUi: params.dialogUi,
204
+ categories: params.categories,
205
+ preselectedCategories: params.preselectedCategories,
206
+ gpc: params.gpc,
207
+ proofConfig: params.proofConfig,
208
+ iat,
209
+ exp
210
+ };
211
+ const token = await new SignJWT(payload).setProtectedHeader(POLICY_SNAPSHOT_JWT_HEADER).setIssuedAt(iat).setExpirationTime(exp).sign(getSigningKey(options.signingKey));
212
+ return {
213
+ token,
214
+ payload
215
+ };
216
+ }
217
+ async function verifyPolicySnapshotToken(params) {
218
+ const { token, options, tenantId } = params;
219
+ if (!options?.signingKey) return {
220
+ valid: false,
221
+ reason: 'missing'
222
+ };
223
+ if (!token) return {
224
+ valid: false,
225
+ reason: 'missing'
226
+ };
227
+ if (3 !== token.split('.').length) return {
228
+ valid: false,
229
+ reason: 'malformed'
230
+ };
231
+ try {
232
+ const { payload, protectedHeader } = await jwtVerify(token, getSigningKey(options.signingKey), {
233
+ issuer: resolveSnapshotIssuer(options),
234
+ audience: resolveSnapshotAudience({
235
+ options,
236
+ tenantId
237
+ })
238
+ });
239
+ const header = protectedHeader;
240
+ if ('HS256' !== header.alg || 'JWT' !== header.typ) return {
241
+ valid: false,
242
+ reason: 'invalid'
243
+ };
244
+ if (!isPolicySnapshotPayload(payload)) return {
245
+ valid: false,
246
+ reason: 'invalid'
247
+ };
248
+ if (payload.sub !== payload.policyId) return {
249
+ valid: false,
250
+ reason: 'invalid'
251
+ };
252
+ if ((tenantId ?? void 0) !== (payload.tenantId ?? void 0)) return {
253
+ valid: false,
254
+ reason: 'invalid'
255
+ };
256
+ return {
257
+ valid: true,
258
+ payload
259
+ };
260
+ } catch (error) {
261
+ if (error instanceof errors.JWTExpired) return {
262
+ valid: false,
263
+ reason: 'expired'
264
+ };
265
+ return {
266
+ valid: false,
267
+ reason: 'invalid'
268
+ };
269
+ }
270
+ }
271
+ function normalizeHeader(value) {
272
+ if (!value) return null;
273
+ return Array.isArray(value) ? value[0] ?? null : value;
274
+ }
275
+ function getGeoHeaders(headers) {
276
+ const countryCode = normalizeHeader(headers.get('x-c15t-country')) ?? normalizeHeader(headers.get('cf-ipcountry')) ?? normalizeHeader(headers.get('x-vercel-ip-country')) ?? normalizeHeader(headers.get('x-amz-cf-ipcountry')) ?? normalizeHeader(headers.get('x-country-code'));
277
+ const regionCode = normalizeHeader(headers.get('x-c15t-region')) ?? normalizeHeader(headers.get('x-vercel-ip-country-region')) ?? normalizeHeader(headers.get('x-region-code'));
278
+ return {
279
+ countryCode,
280
+ regionCode
281
+ };
282
+ }
283
+ function checkJurisdiction(countryCode, regionCode) {
284
+ const jurisdictions = {
285
+ EU: new Set([
286
+ 'AT',
287
+ 'BE',
288
+ 'BG',
289
+ 'HR',
290
+ 'CY',
291
+ 'CZ',
292
+ 'DK',
293
+ 'EE',
294
+ 'FI',
295
+ 'FR',
296
+ 'DE',
297
+ 'GR',
298
+ 'HU',
299
+ 'IE',
300
+ 'IT',
301
+ 'LV',
302
+ 'LT',
303
+ 'LU',
304
+ 'MT',
305
+ 'NL',
306
+ 'PL',
307
+ 'PT',
308
+ 'RO',
309
+ 'SK',
310
+ 'SI',
311
+ 'ES',
312
+ 'SE'
313
+ ]),
314
+ EEA: new Set([
315
+ 'IS',
316
+ 'NO',
317
+ 'LI'
318
+ ]),
319
+ UK: new Set([
320
+ 'GB'
321
+ ]),
322
+ CH: new Set([
323
+ 'CH'
324
+ ]),
325
+ BR: new Set([
326
+ 'BR'
327
+ ]),
328
+ CA: new Set([
329
+ 'CA'
330
+ ]),
331
+ AU: new Set([
332
+ 'AU'
333
+ ]),
334
+ JP: new Set([
335
+ 'JP'
336
+ ]),
337
+ KR: new Set([
338
+ 'KR'
339
+ ]),
340
+ US_CCPA_REGIONS: new Set([
341
+ 'CA'
342
+ ]),
343
+ CA_QC_REGIONS: new Set([
344
+ 'QC'
345
+ ])
346
+ };
347
+ let jurisdiction = 'NONE';
348
+ if (countryCode) {
349
+ const normalizedCountryCode = countryCode.toUpperCase();
350
+ const normalizedRegionCode = regionCode && 'string' == typeof regionCode ? (regionCode.includes('-') ? regionCode.split('-').pop() : regionCode).toUpperCase() : null;
351
+ if ('US' === normalizedCountryCode && normalizedRegionCode && jurisdictions.US_CCPA_REGIONS.has(normalizedRegionCode)) return 'CCPA';
352
+ if ('CA' === normalizedCountryCode && normalizedRegionCode && jurisdictions.CA_QC_REGIONS.has(normalizedRegionCode)) return 'QC_LAW25';
353
+ const jurisdictionMap = [
354
+ {
355
+ sets: [
356
+ jurisdictions.UK
357
+ ],
358
+ code: 'UK_GDPR'
359
+ },
360
+ {
361
+ sets: [
362
+ jurisdictions.EU,
363
+ jurisdictions.EEA
364
+ ],
365
+ code: 'GDPR'
366
+ },
367
+ {
368
+ sets: [
369
+ jurisdictions.CH
370
+ ],
371
+ code: 'CH'
372
+ },
373
+ {
374
+ sets: [
375
+ jurisdictions.BR
376
+ ],
377
+ code: 'BR'
378
+ },
379
+ {
380
+ sets: [
381
+ jurisdictions.CA
382
+ ],
383
+ code: 'PIPEDA'
384
+ },
385
+ {
386
+ sets: [
387
+ jurisdictions.AU
388
+ ],
389
+ code: 'AU'
390
+ },
391
+ {
392
+ sets: [
393
+ jurisdictions.JP
394
+ ],
395
+ code: 'APPI'
396
+ },
397
+ {
398
+ sets: [
399
+ jurisdictions.KR
400
+ ],
401
+ code: 'PIPA'
402
+ }
403
+ ];
404
+ for (const { sets, code } of jurisdictionMap)if (sets.some((set)=>set.has(normalizedCountryCode))) {
405
+ jurisdiction = code;
406
+ break;
407
+ }
408
+ }
409
+ return jurisdiction;
410
+ }
411
+ async function getLocation(request, options) {
412
+ if (options.disableGeoLocation) return {
413
+ countryCode: null,
414
+ regionCode: null
415
+ };
416
+ const { countryCode, regionCode } = getGeoHeaders(request.headers);
417
+ return {
418
+ countryCode,
419
+ regionCode
420
+ };
421
+ }
422
+ function getJurisdiction(location, options) {
423
+ if (options.disableGeoLocation) return 'GDPR';
424
+ return checkJurisdiction(location.countryCode, location.regionCode);
425
+ }
426
+ function stripIabTranslations(translations) {
427
+ const { iab: _iab, ...rest } = translations;
428
+ return rest;
429
+ }
430
+ function resolveNoPolicyFallback() {
431
+ return {
432
+ id: 'no_banner',
433
+ model: 'none',
434
+ ui: {
435
+ mode: 'none'
436
+ }
437
+ };
438
+ }
439
+ async function resolveInitPayload(request, options, logger) {
440
+ const acceptLanguage = request.headers.get('accept-language') || 'en';
441
+ const location = await getLocation(request, options);
442
+ const jurisdiction = getJurisdiction(location, options);
443
+ const hasExplicitPolicyPack = void 0 !== options.policyPacks;
444
+ const isExplicitEmptyPolicyPack = hasExplicitPolicyPack && (options.policyPacks?.length ?? 0) === 0;
445
+ const policyDecision = isExplicitEmptyPolicyPack ? void 0 : await policy_resolvePolicyDecision({
446
+ policies: options.policyPacks,
447
+ countryCode: location.countryCode,
448
+ regionCode: location.regionCode,
449
+ jurisdiction,
450
+ iabEnabled: options.iab?.enabled === true
451
+ });
452
+ if (hasExplicitPolicyPack && !isExplicitEmptyPolicyPack && !policyDecision) logger?.warn('Policy packs configured but no policy matched', {
453
+ country: location.countryCode,
454
+ region: location.regionCode
455
+ });
456
+ const resolvedPolicy = hasExplicitPolicyPack ? policyDecision?.policy ?? resolveNoPolicyFallback() : void 0;
457
+ const iabOptions = options.iab;
458
+ const shouldIncludeIabPayload = iabOptions?.enabled === true && (!hasExplicitPolicyPack || resolvedPolicy?.model === 'iab');
459
+ const translationsResult = getTranslationsData(acceptLanguage, options.customTranslations, {
460
+ i18n: options.i18n,
461
+ policyI18n: resolvedPolicy?.i18n,
462
+ logger
463
+ });
464
+ const responseTranslations = shouldIncludeIabPayload ? translationsResult : {
465
+ ...translationsResult,
466
+ translations: stripIabTranslations(translationsResult.translations)
467
+ };
468
+ let gvl = null;
469
+ if (shouldIncludeIabPayload && iabOptions) {
470
+ const language = translationsResult.language.split('-')[0] || 'en';
471
+ const gvlResolver = createGVLResolver({
472
+ appName: options.appName || 'c15t',
473
+ bundled: iabOptions.bundled,
474
+ cacheAdapter: options.cache?.adapter,
475
+ vendorIds: iabOptions.vendorIds,
476
+ endpoint: iabOptions.endpoint
477
+ });
478
+ gvl = await gvlResolver.get(language);
479
+ }
480
+ const customVendors = shouldIncludeIabPayload ? iabOptions?.customVendors : void 0;
481
+ const snapshot = policyDecision ? await createPolicySnapshotToken({
482
+ options: options.policySnapshot,
483
+ tenantId: options.tenantId,
484
+ policyId: policyDecision.policy.id,
485
+ fingerprint: policyDecision.fingerprint,
486
+ matchedBy: policyDecision.matchedBy,
487
+ country: location?.countryCode ?? null,
488
+ region: location?.regionCode ?? null,
489
+ jurisdiction,
490
+ language: translationsResult.language,
491
+ model: policyDecision.policy.model,
492
+ policyI18n: policyDecision.policy.i18n,
493
+ expiryDays: policyDecision.policy.consent?.expiryDays,
494
+ scopeMode: policyDecision.policy.consent?.scopeMode,
495
+ uiMode: policyDecision.policy.ui?.mode,
496
+ bannerUi: policyDecision.policy.ui?.banner,
497
+ dialogUi: policyDecision.policy.ui?.dialog,
498
+ categories: policyDecision.policy.consent?.categories,
499
+ preselectedCategories: policyDecision.policy.consent?.preselectedCategories,
500
+ gpc: policyDecision.policy.consent?.gpc,
501
+ proofConfig: policyDecision.policy.proof
502
+ }) : void 0;
503
+ const gpc = '1' === request.headers.get('sec-gpc');
504
+ getMetrics()?.recordInit({
505
+ jurisdiction,
506
+ country: location?.countryCode ?? void 0,
507
+ region: location?.regionCode ?? void 0,
508
+ gpc
509
+ });
510
+ return {
511
+ jurisdiction,
512
+ location,
513
+ translations: responseTranslations,
514
+ branding: options.branding || 'c15t',
515
+ ...shouldIncludeIabPayload && {
516
+ gvl,
517
+ customVendors
518
+ },
519
+ ...resolvedPolicy && {
520
+ policy: resolvedPolicy
521
+ },
522
+ ...policyDecision && {
523
+ policyDecision: {
524
+ policyId: policyDecision.policy.id,
525
+ fingerprint: policyDecision.fingerprint,
526
+ matchedBy: policyDecision.matchedBy,
527
+ country: location.countryCode,
528
+ region: location.regionCode,
529
+ jurisdiction
530
+ }
531
+ },
532
+ ...snapshot?.token && {
533
+ policySnapshotToken: snapshot.token
534
+ },
535
+ ...shouldIncludeIabPayload && iabOptions?.cmpId != null && {
536
+ cmpId: iabOptions.cmpId
537
+ }
538
+ };
539
+ }
540
+ export { checkJurisdiction, getJurisdiction, getLocation, policy_inspectPolicies as inspectPolicies, policy_resolvePolicyDecision, policy_resolvePolicySync, resolveInitPayload, validateMessages, verifyPolicySnapshotToken };