@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
@@ -1,451 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
- import type { ConsentPolicy, PolicyType } from '../schema';
3
- import { policyRegistry } from './consent-policy';
4
- import type { Registry } from './types';
5
-
6
- describe('policyRegistry', () => {
7
- const mockLogger = {
8
- debug: vi.fn(),
9
- error: vi.fn(),
10
- info: vi.fn(),
11
- warn: vi.fn(),
12
- };
13
-
14
- vi.mock('./utils/generate-id', () => ({
15
- generateUniqueId: vi.fn().mockResolvedValue('pol_test'),
16
- }));
17
-
18
- /**
19
- * Creates a mock consent policy object with the specified overrides
20
- *
21
- * @param overrides - Partial consent policy properties to override defaults
22
- * @returns A complete ConsentPolicy object for testing
23
- */
24
- const createMockConsentPolicy = (
25
- overrides: Partial<ConsentPolicy> = {}
26
- ): ConsentPolicy => ({
27
- id: 'pol_test',
28
- version: '1.0.0',
29
- type: 'privacy_policy',
30
- effectiveDate: new Date('2024-01-01T00:00:00.000Z'),
31
- isActive: true,
32
- createdAt: new Date('2024-01-01T00:00:00.000Z'),
33
- ...overrides,
34
- });
35
-
36
- afterEach(() => {
37
- vi.clearAllMocks();
38
- });
39
-
40
- describe('findConsentPolicyById', () => {
41
- it('should return policy when found by id', async () => {
42
- const mockPolicy = createMockConsentPolicy({
43
- id: 'pol_specific_123',
44
- type: 'cookie_banner',
45
- });
46
-
47
- const db = {
48
- findFirst: vi.fn().mockResolvedValue(mockPolicy),
49
- };
50
-
51
- const registry = policyRegistry({
52
- db,
53
- ctx: { logger: mockLogger },
54
- } as unknown as Registry);
55
-
56
- const result = await registry.findConsentPolicyById('pol_specific_123');
57
-
58
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
59
- where: expect.any(Function),
60
- });
61
-
62
- expect(result).toEqual(mockPolicy);
63
- });
64
-
65
- it('should return null when policy not found by id', async () => {
66
- const db = {
67
- findFirst: vi.fn().mockResolvedValue(null),
68
- };
69
-
70
- const registry = policyRegistry({
71
- db,
72
- ctx: { logger: mockLogger },
73
- } as unknown as Registry);
74
-
75
- const result = await registry.findConsentPolicyById('nonexistent_id');
76
-
77
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
78
- where: expect.any(Function),
79
- });
80
-
81
- expect(result).toBeNull();
82
- });
83
-
84
- it('should handle various policy id formats', async () => {
85
- const testIds = [
86
- 'pol_123',
87
- 'policy_test_long_id_name',
88
- 'SHORT',
89
- 'ID_WITH_UNDERSCORES',
90
- 'mixed.Case-id_123',
91
- ];
92
-
93
- for (const testId of testIds) {
94
- const mockPolicy = createMockConsentPolicy({ id: testId });
95
-
96
- const db = {
97
- findFirst: vi.fn().mockResolvedValue(mockPolicy),
98
- };
99
-
100
- const registry = policyRegistry({
101
- db,
102
- ctx: { logger: mockLogger },
103
- } as unknown as Registry);
104
-
105
- const result = await registry.findConsentPolicyById(testId);
106
-
107
- expect(result?.id).toBe(testId);
108
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
109
- where: expect.any(Function),
110
- });
111
-
112
- vi.clearAllMocks();
113
- }
114
- });
115
-
116
- it('should propagate database errors', async () => {
117
- const dbError = new Error('Database connection failed');
118
- const db = {
119
- findFirst: vi.fn().mockRejectedValue(dbError),
120
- };
121
-
122
- const registry = policyRegistry({
123
- db,
124
- ctx: { logger: mockLogger },
125
- } as unknown as Registry);
126
-
127
- const promise = registry.findConsentPolicyById('error_id');
128
-
129
- await expect(promise).rejects.toThrow('Database connection failed');
130
- });
131
- });
132
-
133
- describe('findOrCreatePolicy', () => {
134
- describe('when policy exists', () => {
135
- it('should return existing active policy for given type', async () => {
136
- const mockPolicy = createMockConsentPolicy({
137
- type: 'terms_and_conditions',
138
- version: '2.1.0',
139
- isActive: true,
140
- });
141
-
142
- const db = {
143
- findFirst: vi.fn().mockResolvedValue(mockPolicy),
144
- create: vi.fn(),
145
- };
146
-
147
- const registry = policyRegistry({
148
- db,
149
- ctx: { logger: mockLogger },
150
- } as unknown as Registry);
151
-
152
- const result = await registry.findOrCreatePolicy(
153
- 'terms_and_conditions'
154
- );
155
-
156
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
157
- where: expect.any(Function),
158
- orderBy: ['effectiveDate', 'desc'],
159
- });
160
-
161
- expect(db.create).not.toHaveBeenCalled();
162
- expect(result).toEqual(mockPolicy);
163
- expect(mockLogger.debug).toHaveBeenCalledWith('Found existing policy', {
164
- type: 'terms_and_conditions',
165
- policyId: mockPolicy.id,
166
- });
167
- });
168
-
169
- it('should handle all valid policy types', async () => {
170
- const validPolicyTypes: PolicyType[] = [
171
- 'cookie_banner',
172
- 'privacy_policy',
173
- 'dpa',
174
- 'terms_and_conditions',
175
- 'marketing_communications',
176
- 'age_verification',
177
- 'other',
178
- ];
179
-
180
- for (const policyType of validPolicyTypes) {
181
- const mockPolicy = createMockConsentPolicy({
182
- type: policyType,
183
- });
184
-
185
- const db = {
186
- findFirst: vi.fn().mockResolvedValue(mockPolicy),
187
- create: vi.fn(),
188
- };
189
-
190
- const registry = policyRegistry({
191
- db,
192
- ctx: { logger: mockLogger },
193
- } as unknown as Registry);
194
-
195
- const result = await registry.findOrCreatePolicy(policyType);
196
-
197
- expect(result.type).toBe(policyType);
198
- expect(db.create).not.toHaveBeenCalled();
199
-
200
- vi.clearAllMocks();
201
- }
202
- });
203
-
204
- it('should return most recent active policy when multiple exist', async () => {
205
- const mostRecentPolicy = createMockConsentPolicy({
206
- id: 'pol_most_recent',
207
- effectiveDate: new Date('2024-03-01T00:00:00.000Z'),
208
- version: '3.0.0',
209
- });
210
-
211
- const db = {
212
- findFirst: vi.fn().mockResolvedValue(mostRecentPolicy),
213
- create: vi.fn(),
214
- };
215
-
216
- const registry = policyRegistry({
217
- db,
218
- ctx: { logger: mockLogger },
219
- } as unknown as Registry);
220
-
221
- const result = await registry.findOrCreatePolicy('privacy_policy');
222
-
223
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
224
- where: expect.any(Function),
225
- orderBy: ['effectiveDate', 'desc'],
226
- });
227
-
228
- expect(result).toEqual(mostRecentPolicy);
229
- expect(result.id).toBe('pol_most_recent');
230
- });
231
- });
232
-
233
- describe('when policy does not exist', () => {
234
- it('should create new policy with minimal fields', async () => {
235
- const fakeDate = new Date('2024-01-15T10:30:00.000Z');
236
- vi.useFakeTimers();
237
- vi.setSystemTime(fakeDate);
238
-
239
- const newMockPolicy = createMockConsentPolicy({
240
- id: 'pol_test',
241
- type: 'dpa',
242
- effectiveDate: fakeDate,
243
- });
244
-
245
- const db = {
246
- findFirst: vi.fn().mockResolvedValue(null),
247
- create: vi.fn().mockResolvedValue(newMockPolicy),
248
- };
249
-
250
- const registry = policyRegistry({
251
- db,
252
- ctx: { logger: mockLogger },
253
- } as unknown as Registry);
254
-
255
- const result = await registry.findOrCreatePolicy('dpa');
256
-
257
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
258
- where: expect.any(Function),
259
- orderBy: ['effectiveDate', 'desc'],
260
- });
261
-
262
- expect(db.create).toHaveBeenCalledWith('consentPolicy', {
263
- id: 'pol_test',
264
- version: '1.0.0',
265
- type: 'dpa',
266
- effectiveDate: fakeDate,
267
- isActive: true,
268
- });
269
-
270
- expect(result).toEqual(newMockPolicy);
271
-
272
- vi.useRealTimers();
273
- });
274
-
275
- it('should create policies for all valid types with correct defaults', async () => {
276
- const validPolicyTypes: PolicyType[] = [
277
- 'cookie_banner',
278
- 'privacy_policy',
279
- 'dpa',
280
- 'terms_and_conditions',
281
- 'marketing_communications',
282
- 'age_verification',
283
- 'other',
284
- ];
285
-
286
- const fakeDate = new Date('2024-02-01T00:00:00.000Z');
287
- vi.useFakeTimers();
288
- vi.setSystemTime(fakeDate);
289
-
290
- for (const policyType of validPolicyTypes) {
291
- const mockPolicy = createMockConsentPolicy({
292
- type: policyType,
293
- effectiveDate: fakeDate,
294
- });
295
-
296
- const db = {
297
- findFirst: vi.fn().mockResolvedValue(null),
298
- create: vi.fn().mockResolvedValue(mockPolicy),
299
- };
300
-
301
- const registry = policyRegistry({
302
- db,
303
- ctx: { logger: mockLogger },
304
- } as unknown as Registry);
305
-
306
- const result = await registry.findOrCreatePolicy(policyType);
307
-
308
- expect(db.create).toHaveBeenCalledWith('consentPolicy', {
309
- id: 'pol_test',
310
- version: '1.0.0',
311
- type: policyType,
312
- effectiveDate: fakeDate,
313
- isActive: true,
314
- });
315
-
316
- expect(result.type).toBe(policyType);
317
- expect(result.version).toBe('1.0.0');
318
- expect(result.isActive).toBe(true);
319
-
320
- vi.clearAllMocks();
321
- }
322
-
323
- vi.useRealTimers();
324
- });
325
- });
326
-
327
- describe('error handling', () => {
328
- it('should propagate database findFirst errors', async () => {
329
- const dbError = new Error('Database query failed');
330
- const db = {
331
- findFirst: vi.fn().mockRejectedValue(dbError),
332
- };
333
-
334
- const registry = policyRegistry({
335
- db,
336
- ctx: { logger: mockLogger },
337
- } as unknown as Registry);
338
-
339
- const promise = registry.findOrCreatePolicy('privacy_policy');
340
-
341
- await expect(promise).rejects.toThrow('Database query failed');
342
- });
343
-
344
- it('should propagate database create errors', async () => {
345
- const dbError = new Error('Create operation failed');
346
- const db = {
347
- findFirst: vi.fn().mockResolvedValue(null),
348
- create: vi.fn().mockRejectedValue(dbError),
349
- };
350
-
351
- const registry = policyRegistry({
352
- db,
353
- ctx: { logger: mockLogger },
354
- } as unknown as Registry);
355
-
356
- const promise = registry.findOrCreatePolicy('privacy_policy');
357
-
358
- await expect(promise).rejects.toThrow('Create operation failed');
359
- });
360
- });
361
- });
362
-
363
- describe('database query construction', () => {
364
- it('should construct correct query for policy lookup by id', async () => {
365
- const db = {
366
- findFirst: vi.fn().mockResolvedValue(null),
367
- };
368
-
369
- const registry = policyRegistry({
370
- db,
371
- ctx: { logger: mockLogger },
372
- } as unknown as Registry);
373
-
374
- await registry.findConsentPolicyById('test_id');
375
-
376
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
377
- where: expect.any(Function),
378
- });
379
-
380
- const whereCall = db.findFirst.mock.calls[0]?.[1];
381
- expect(whereCall).toHaveProperty('where');
382
- expect(typeof whereCall?.where).toBe('function');
383
- });
384
-
385
- it('should construct correct query for active policy lookup by type', async () => {
386
- const db = {
387
- findFirst: vi.fn().mockResolvedValue(null),
388
- create: vi.fn().mockResolvedValue(createMockConsentPolicy()),
389
- };
390
-
391
- const registry = policyRegistry({
392
- db,
393
- ctx: { logger: mockLogger },
394
- } as unknown as Registry);
395
-
396
- await registry.findOrCreatePolicy('privacy_policy');
397
-
398
- expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
399
- where: expect.any(Function),
400
- orderBy: ['effectiveDate', 'desc'],
401
- });
402
-
403
- const findCall = db.findFirst.mock.calls[0]?.[1];
404
- expect(findCall).toHaveProperty('where');
405
- expect(findCall).toHaveProperty('orderBy');
406
- expect(findCall?.orderBy).toEqual(['effectiveDate', 'desc']);
407
- });
408
- });
409
-
410
- describe('edge cases', () => {
411
- it('should handle concurrent policy creation requests', async () => {
412
- const fakeDate = new Date('2024-01-01T00:00:00.000Z');
413
- vi.useFakeTimers();
414
- vi.setSystemTime(fakeDate);
415
-
416
- const mockPolicy = createMockConsentPolicy({
417
- type: 'privacy_policy',
418
- effectiveDate: fakeDate,
419
- });
420
-
421
- const db = {
422
- findFirst: vi.fn().mockResolvedValue(null),
423
- create: vi.fn().mockResolvedValue(mockPolicy),
424
- };
425
-
426
- const registry = policyRegistry({
427
- db,
428
- ctx: { logger: mockLogger },
429
- } as unknown as Registry);
430
-
431
- // Simulate concurrent requests
432
- const promises = [
433
- registry.findOrCreatePolicy('privacy_policy'),
434
- registry.findOrCreatePolicy('privacy_policy'),
435
- registry.findOrCreatePolicy('privacy_policy'),
436
- ];
437
-
438
- const results = await Promise.all(promises);
439
-
440
- // All should succeed (actual uniqueness would be handled by database constraints)
441
- expect(results).toHaveLength(3);
442
- for (const result of results) {
443
- expect(result.type).toBe('privacy_policy');
444
- }
445
-
446
- expect(db.create).toHaveBeenCalledTimes(3);
447
-
448
- vi.useRealTimers();
449
- });
450
- });
451
- });
@@ -1,82 +0,0 @@
1
- import { withDatabaseSpan } from '~/utils/instrumentation';
2
- import { getMetrics } from '~/utils/metrics';
3
- import type { PolicyType } from '../schema';
4
- import type { Registry } from './types';
5
- import { generateUniqueId } from './utils/generate-id';
6
-
7
- export function policyRegistry({ db, ctx }: Registry) {
8
- const { logger } = ctx;
9
-
10
- return {
11
- findConsentPolicyById: async (policyId: string) => {
12
- const start = Date.now();
13
- try {
14
- const result = await withDatabaseSpan(
15
- { operation: 'find', entity: 'consentPolicy' },
16
- async () => {
17
- const policy = await db.findFirst('consentPolicy', {
18
- where: (b) => b('id', '=', policyId),
19
- });
20
- return policy;
21
- }
22
- );
23
- getMetrics()?.recordDbQuery(
24
- { operation: 'find', entity: 'consentPolicy' },
25
- Date.now() - start
26
- );
27
- return result;
28
- } catch (error) {
29
- getMetrics()?.recordDbError({
30
- operation: 'find',
31
- entity: 'consentPolicy',
32
- });
33
- throw error;
34
- }
35
- },
36
- findOrCreatePolicy: async (type: PolicyType) => {
37
- const start = Date.now();
38
- try {
39
- const result = await withDatabaseSpan(
40
- { operation: 'findOrCreate', entity: 'consentPolicy' },
41
- async () => {
42
- // Gets most recent active policy for a given type
43
- const existingPolicy = await db.findFirst('consentPolicy', {
44
- where: (b) =>
45
- b.and(b('isActive', '=', true), b('type', '=', type)),
46
- orderBy: ['effectiveDate', 'desc'],
47
- });
48
-
49
- if (existingPolicy) {
50
- logger.debug('Found existing policy', {
51
- type,
52
- policyId: existingPolicy.id,
53
- });
54
- return existingPolicy;
55
- }
56
-
57
- const policy = await db.create('consentPolicy', {
58
- id: await generateUniqueId(db, 'consentPolicy', ctx),
59
- version: '1.0.0',
60
- type,
61
- effectiveDate: new Date(),
62
- isActive: true,
63
- });
64
-
65
- return policy;
66
- }
67
- );
68
- getMetrics()?.recordDbQuery(
69
- { operation: 'findOrCreate', entity: 'consentPolicy' },
70
- Date.now() - start
71
- );
72
- return result;
73
- } catch (error) {
74
- getMetrics()?.recordDbError({
75
- operation: 'findOrCreate',
76
- entity: 'consentPolicy',
77
- });
78
- throw error;
79
- }
80
- },
81
- };
82
- }