@c15t/backend 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (489) hide show
  1. package/.turbo/turbo-build.log +63 -37
  2. package/CHANGELOG.md +4 -209
  3. package/README.md +86 -164
  4. package/dist/contracts/consent/index.d.ts +103 -615
  5. package/dist/contracts/consent/index.d.ts.map +1 -1
  6. package/dist/contracts/consent/post.contract.d.ts +42 -140
  7. package/dist/contracts/consent/post.contract.d.ts.map +1 -1
  8. package/dist/contracts/consent/show-banner.contract.d.ts +28 -376
  9. package/dist/contracts/consent/show-banner.contract.d.ts.map +1 -1
  10. package/dist/contracts/consent/verify.contract.d.ts +33 -99
  11. package/dist/contracts/consent/verify.contract.d.ts.map +1 -1
  12. package/dist/contracts/index.d.ts +222 -1356
  13. package/dist/contracts/index.d.ts.map +1 -1
  14. package/dist/contracts/meta/index.d.ts +8 -63
  15. package/dist/contracts/meta/index.d.ts.map +1 -1
  16. package/dist/contracts/meta/status.contract.d.ts +8 -63
  17. package/dist/contracts/meta/status.contract.d.ts.map +1 -1
  18. package/dist/contracts/shared/jurisdiction.schema.d.ts +21 -9
  19. package/dist/contracts/shared/jurisdiction.schema.d.ts.map +1 -1
  20. package/dist/contracts.cjs +100 -106
  21. package/dist/contracts.js +100 -106
  22. package/dist/core.cjs +681 -681
  23. package/dist/core.d.ts +118 -678
  24. package/dist/core.d.ts.map +1 -1
  25. package/dist/core.js +634 -637
  26. package/dist/handlers/consent/index.d.ts +103 -615
  27. package/dist/handlers/consent/index.d.ts.map +1 -1
  28. package/dist/handlers/consent/post.handler.d.ts +42 -140
  29. package/dist/handlers/consent/post.handler.d.ts.map +1 -1
  30. package/dist/handlers/consent/show-banner/handler.d.ts +28 -376
  31. package/dist/handlers/consent/show-banner/handler.d.ts.map +1 -1
  32. package/dist/handlers/consent/show-banner/translations.d.ts.map +1 -1
  33. package/dist/handlers/consent/verify.handler.d.ts +33 -99
  34. package/dist/handlers/consent/verify.handler.d.ts.map +1 -1
  35. package/dist/handlers/meta/index.d.ts +8 -63
  36. package/dist/handlers/meta/index.d.ts.map +1 -1
  37. package/dist/handlers/meta/status.handler.d.ts +8 -63
  38. package/dist/handlers/meta/status.handler.d.ts.map +1 -1
  39. package/dist/init.d.ts.map +1 -1
  40. package/dist/middleware/openapi/index.d.ts +2 -2
  41. package/dist/middleware/openapi/index.d.ts.map +1 -1
  42. package/dist/pkgs/data-model/fields/index.cjs +14 -26
  43. package/dist/pkgs/data-model/fields/index.d.ts +4 -4
  44. package/dist/pkgs/data-model/fields/index.d.ts.map +1 -1
  45. package/dist/pkgs/data-model/fields/index.js +14 -26
  46. package/dist/pkgs/data-model/fields/zod-fields.d.ts +195 -871
  47. package/dist/pkgs/data-model/fields/zod-fields.d.ts.map +1 -1
  48. package/dist/pkgs/data-model/hooks/index.d.ts +2 -2
  49. package/dist/pkgs/data-model/hooks/index.d.ts.map +1 -1
  50. package/dist/pkgs/data-model/index.cjs +346 -358
  51. package/dist/pkgs/data-model/index.d.ts +1 -1
  52. package/dist/pkgs/data-model/index.d.ts.map +1 -1
  53. package/dist/pkgs/data-model/index.js +345 -357
  54. package/dist/pkgs/data-model/schema/index.cjs +346 -358
  55. package/dist/pkgs/data-model/schema/index.d.ts +1 -1
  56. package/dist/pkgs/data-model/schema/index.d.ts.map +1 -1
  57. package/dist/pkgs/data-model/schema/index.js +345 -357
  58. package/dist/pkgs/data-model/schema/schemas.d.ts +2 -2
  59. package/dist/pkgs/data-model/schema/schemas.d.ts.map +1 -1
  60. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.d.ts +3 -0
  61. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.d.ts.map +1 -1
  62. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.cjs +158 -170
  63. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.js +157 -169
  64. package/dist/pkgs/db-adapters/adapters/index.d.ts +2 -2
  65. package/dist/pkgs/db-adapters/adapters/index.d.ts.map +1 -1
  66. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.cjs +215 -227
  67. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.d.ts +2 -2
  68. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.d.ts.map +1 -1
  69. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.js +213 -225
  70. package/dist/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.d.ts +2 -0
  71. package/dist/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.d.ts.map +1 -1
  72. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts +1 -1
  73. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts.map +1 -1
  74. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.cjs +158 -170
  75. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.js +157 -169
  76. package/dist/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.d.ts +3 -0
  77. package/dist/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.d.ts.map +1 -1
  78. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.cjs +243 -255
  79. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.d.ts +1 -1
  80. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.d.ts.map +1 -1
  81. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.js +241 -253
  82. package/dist/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.d.ts +3 -0
  83. package/dist/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.d.ts.map +1 -1
  84. package/dist/pkgs/db-adapters/index.cjs +714 -726
  85. package/dist/pkgs/db-adapters/index.d.ts +6 -6
  86. package/dist/pkgs/db-adapters/index.d.ts.map +1 -1
  87. package/dist/pkgs/db-adapters/index.js +708 -720
  88. package/dist/pkgs/migrations/get-migration.d.ts.map +1 -1
  89. package/dist/pkgs/migrations/get-schema/get-schema.d.ts.map +1 -1
  90. package/dist/pkgs/migrations/get-schema/process-tables.d.ts.map +1 -1
  91. package/dist/pkgs/migrations/index.cjs +236 -248
  92. package/dist/pkgs/migrations/index.d.ts +4 -4
  93. package/dist/pkgs/migrations/index.d.ts.map +1 -1
  94. package/dist/pkgs/migrations/index.js +235 -247
  95. package/dist/pkgs/results/index.cjs +67 -67
  96. package/dist/pkgs/results/index.d.ts +5 -5
  97. package/dist/pkgs/results/index.d.ts.map +1 -1
  98. package/dist/pkgs/results/index.js +67 -67
  99. package/dist/pkgs/results/orpc-error-handler.d.ts +1 -1
  100. package/dist/pkgs/results/orpc-error-handler.d.ts.map +1 -1
  101. package/dist/pkgs/types/index.d.ts +1 -2
  102. package/dist/pkgs/types/index.d.ts.map +1 -1
  103. package/dist/pkgs/types/options.d.ts +9 -2
  104. package/dist/pkgs/types/options.d.ts.map +1 -1
  105. package/dist/pkgs/utils/index.d.ts +1 -1
  106. package/dist/pkgs/utils/index.d.ts.map +1 -1
  107. package/dist/pkgs/utils/logger.d.ts +1 -1
  108. package/dist/pkgs/utils/logger.d.ts.map +1 -1
  109. package/dist/router.cjs +114 -117
  110. package/dist/router.d.ts +111 -678
  111. package/dist/router.d.ts.map +1 -1
  112. package/dist/router.js +114 -117
  113. package/dist/schema/audit-log/schema.d.ts +2 -24
  114. package/dist/schema/audit-log/schema.d.ts.map +1 -1
  115. package/dist/schema/audit-log/table.d.ts +2 -24
  116. package/dist/schema/audit-log/table.d.ts.map +1 -1
  117. package/dist/schema/consent/registry.d.ts +8 -8
  118. package/dist/schema/consent/schema.d.ts +9 -33
  119. package/dist/schema/consent/schema.d.ts.map +1 -1
  120. package/dist/schema/consent/table.d.ts +9 -33
  121. package/dist/schema/consent/table.d.ts.map +1 -1
  122. package/dist/schema/consent-policy/registry.d.ts +20 -20
  123. package/dist/schema/consent-policy/schema.d.ts +22 -30
  124. package/dist/schema/consent-policy/schema.d.ts.map +1 -1
  125. package/dist/schema/consent-policy/table.d.ts +13 -29
  126. package/dist/schema/consent-policy/table.d.ts.map +1 -1
  127. package/dist/schema/consent-purpose/registry.d.ts +6 -6
  128. package/dist/schema/consent-purpose/schema.d.ts +5 -27
  129. package/dist/schema/consent-purpose/schema.d.ts.map +1 -1
  130. package/dist/schema/consent-purpose/table.d.ts +5 -27
  131. package/dist/schema/consent-purpose/table.d.ts.map +1 -1
  132. package/dist/schema/consent-record/schema.d.ts +3 -19
  133. package/dist/schema/consent-record/schema.d.ts.map +1 -1
  134. package/dist/schema/consent-record/table.d.ts +3 -19
  135. package/dist/schema/consent-record/table.d.ts.map +1 -1
  136. package/dist/schema/create-registry.d.ts +58 -58
  137. package/dist/schema/definition.d.ts +42 -176
  138. package/dist/schema/definition.d.ts.map +1 -1
  139. package/dist/schema/domain/registry.d.ts +20 -20
  140. package/dist/schema/domain/schema.d.ts +6 -24
  141. package/dist/schema/domain/schema.d.ts.map +1 -1
  142. package/dist/schema/domain/table.d.ts +6 -24
  143. package/dist/schema/domain/table.d.ts.map +1 -1
  144. package/dist/schema/index.cjs +426 -438
  145. package/dist/schema/index.d.ts +12 -12
  146. package/dist/schema/index.d.ts.map +1 -1
  147. package/dist/schema/index.js +426 -438
  148. package/dist/schema/schemas.d.ts +42 -176
  149. package/dist/schema/schemas.d.ts.map +1 -1
  150. package/dist/schema/subject/registry.d.ts +4 -4
  151. package/dist/schema/subject/schema.d.ts +4 -20
  152. package/dist/schema/subject/schema.d.ts.map +1 -1
  153. package/dist/schema/subject/table.d.ts +4 -20
  154. package/dist/schema/subject/table.d.ts.map +1 -1
  155. package/dist/schema/types.d.ts +1 -1
  156. package/dist/schema/types.d.ts.map +1 -1
  157. package/dist/testing/contract-testing.d.ts +3 -2
  158. package/dist/testing/contract-testing.d.ts.map +1 -1
  159. package/dist/types/index.d.ts +5 -4
  160. package/dist/types/index.d.ts.map +1 -1
  161. package/dist/types/options.d.ts +2 -2
  162. package/dist/types/options.d.ts.map +1 -1
  163. package/dist/v2/contracts/consent/index.d.ts +260 -0
  164. package/dist/v2/contracts/consent/index.d.ts.map +1 -0
  165. package/dist/v2/contracts/consent/index.test.d.ts +2 -0
  166. package/dist/v2/contracts/consent/index.test.d.ts.map +1 -0
  167. package/dist/v2/contracts/consent/post.contract.d.ts +114 -0
  168. package/dist/v2/contracts/consent/post.contract.d.ts.map +1 -0
  169. package/dist/v2/contracts/consent/post.contract.test.d.ts +2 -0
  170. package/dist/v2/contracts/consent/post.contract.test.d.ts.map +1 -0
  171. package/dist/v2/contracts/consent/show-banner.contract.d.ts +68 -0
  172. package/dist/v2/contracts/consent/show-banner.contract.d.ts.map +1 -0
  173. package/dist/v2/contracts/consent/show-banner.contract.test.d.ts +2 -0
  174. package/dist/v2/contracts/consent/show-banner.contract.test.d.ts.map +1 -0
  175. package/dist/v2/contracts/consent/verify.contract.d.ts +81 -0
  176. package/dist/v2/contracts/consent/verify.contract.d.ts.map +1 -0
  177. package/dist/v2/contracts/consent/verify.contract.test.d.ts +2 -0
  178. package/dist/v2/contracts/consent/verify.contract.test.d.ts.map +1 -0
  179. package/dist/v2/contracts/index.cjs +644 -0
  180. package/dist/v2/contracts/index.d.ts +563 -0
  181. package/dist/v2/contracts/index.d.ts.map +1 -0
  182. package/dist/v2/contracts/index.js +607 -0
  183. package/dist/v2/contracts/meta/index.d.ts +19 -0
  184. package/dist/v2/contracts/meta/index.d.ts.map +1 -0
  185. package/dist/v2/contracts/meta/index.test.d.ts +2 -0
  186. package/dist/v2/contracts/meta/index.test.d.ts.map +1 -0
  187. package/dist/v2/contracts/meta/status.contract.d.ts +18 -0
  188. package/dist/v2/contracts/meta/status.contract.d.ts.map +1 -0
  189. package/dist/v2/contracts/meta/status.contract.test.d.ts +2 -0
  190. package/dist/v2/contracts/meta/status.contract.test.d.ts.map +1 -0
  191. package/dist/v2/contracts/shared/jurisdiction.schema.d.ts +36 -0
  192. package/dist/v2/contracts/shared/jurisdiction.schema.d.ts.map +1 -0
  193. package/dist/v2/contracts/test.utils.d.ts +38 -0
  194. package/dist/v2/contracts/test.utils.d.ts.map +1 -0
  195. package/dist/v2/core.cjs +2181 -0
  196. package/dist/v2/core.d.ts +364 -0
  197. package/dist/v2/core.d.ts.map +1 -0
  198. package/dist/v2/core.js +2130 -0
  199. package/dist/v2/db/adapters/drizzle.cjs +36 -0
  200. package/dist/v2/db/adapters/drizzle.d.ts +2 -0
  201. package/dist/v2/db/adapters/drizzle.d.ts.map +1 -0
  202. package/dist/v2/db/adapters/drizzle.js +3 -0
  203. package/dist/v2/db/adapters/index.cjs +18 -0
  204. package/dist/v2/db/adapters/index.d.ts +2 -0
  205. package/dist/v2/db/adapters/index.d.ts.map +1 -0
  206. package/dist/v2/db/adapters/index.js +0 -0
  207. package/dist/v2/db/adapters/kysely.cjs +36 -0
  208. package/dist/v2/db/adapters/kysely.d.ts +2 -0
  209. package/dist/v2/db/adapters/kysely.d.ts.map +1 -0
  210. package/dist/v2/db/adapters/kysely.js +3 -0
  211. package/dist/v2/db/adapters/mongo.cjs +36 -0
  212. package/dist/v2/db/adapters/mongo.d.ts +2 -0
  213. package/dist/v2/db/adapters/mongo.d.ts.map +1 -0
  214. package/dist/v2/db/adapters/mongo.js +3 -0
  215. package/dist/v2/db/adapters/prisma.cjs +36 -0
  216. package/dist/v2/db/adapters/prisma.d.ts +2 -0
  217. package/dist/v2/db/adapters/prisma.d.ts.map +1 -0
  218. package/dist/v2/db/adapters/prisma.js +3 -0
  219. package/dist/v2/db/adapters/typeorm.cjs +36 -0
  220. package/dist/v2/db/adapters/typeorm.d.ts +2 -0
  221. package/dist/v2/db/adapters/typeorm.d.ts.map +1 -0
  222. package/dist/v2/db/adapters/typeorm.js +3 -0
  223. package/dist/v2/db/migrator/index.cjs +61 -0
  224. package/dist/v2/db/migrator/index.d.ts +29 -0
  225. package/dist/v2/db/migrator/index.d.ts.map +1 -0
  226. package/dist/v2/db/migrator/index.js +27 -0
  227. package/dist/v2/db/registry/audit-log.d.ts +21 -0
  228. package/dist/v2/db/registry/audit-log.d.ts.map +1 -0
  229. package/dist/v2/db/registry/audit-log.test.d.ts +2 -0
  230. package/dist/v2/db/registry/audit-log.test.d.ts.map +1 -0
  231. package/dist/v2/db/registry/consent-policy.d.ts +29 -0
  232. package/dist/v2/db/registry/consent-policy.d.ts.map +1 -0
  233. package/dist/v2/db/registry/consent-policy.test.d.ts +2 -0
  234. package/dist/v2/db/registry/consent-policy.test.d.ts.map +1 -0
  235. package/dist/v2/db/registry/consent-purpose.d.ts +16 -0
  236. package/dist/v2/db/registry/consent-purpose.d.ts.map +1 -0
  237. package/dist/v2/db/registry/consent-purpose.test.d.ts +2 -0
  238. package/dist/v2/db/registry/consent-purpose.test.d.ts.map +1 -0
  239. package/dist/v2/db/registry/consent.d.ts +20 -0
  240. package/dist/v2/db/registry/consent.d.ts.map +1 -0
  241. package/dist/v2/db/registry/consent.test.d.ts +2 -0
  242. package/dist/v2/db/registry/consent.test.d.ts.map +1 -0
  243. package/dist/v2/db/registry/domain.d.ts +24 -0
  244. package/dist/v2/db/registry/domain.d.ts.map +1 -0
  245. package/dist/v2/db/registry/domain.test.d.ts +2 -0
  246. package/dist/v2/db/registry/domain.test.d.ts.map +1 -0
  247. package/dist/v2/db/registry/index.d.ts +102 -0
  248. package/dist/v2/db/registry/index.d.ts.map +1 -0
  249. package/dist/v2/db/registry/subject.d.ts +18 -0
  250. package/dist/v2/db/registry/subject.d.ts.map +1 -0
  251. package/dist/v2/db/registry/subject.test.d.ts +2 -0
  252. package/dist/v2/db/registry/subject.test.d.ts.map +1 -0
  253. package/dist/v2/db/registry/types.d.ts +10 -0
  254. package/dist/v2/db/registry/types.d.ts.map +1 -0
  255. package/dist/v2/db/registry/utils/generate-id.d.ts +25 -0
  256. package/dist/v2/db/registry/utils/generate-id.d.ts.map +1 -0
  257. package/dist/v2/db/registry/utils/generate-id.test.d.ts +2 -0
  258. package/dist/v2/db/registry/utils/generate-id.test.d.ts.map +1 -0
  259. package/dist/v2/db/registry/utils.d.ts +25 -0
  260. package/dist/v2/db/registry/utils.d.ts.map +1 -0
  261. package/dist/v2/db/schema/1.0.0/audit-log.d.ts +29 -0
  262. package/dist/v2/db/schema/1.0.0/audit-log.d.ts.map +1 -0
  263. package/dist/v2/db/schema/1.0.0/consent-policy.d.ts +45 -0
  264. package/dist/v2/db/schema/1.0.0/consent-policy.d.ts.map +1 -0
  265. package/dist/v2/db/schema/1.0.0/consent-purpose.d.ts +27 -0
  266. package/dist/v2/db/schema/1.0.0/consent-purpose.d.ts.map +1 -0
  267. package/dist/v2/db/schema/1.0.0/consent-record.d.ts +19 -0
  268. package/dist/v2/db/schema/1.0.0/consent-record.d.ts.map +1 -0
  269. package/dist/v2/db/schema/1.0.0/consent.d.ts +42 -0
  270. package/dist/v2/db/schema/1.0.0/consent.d.ts.map +1 -0
  271. package/dist/v2/db/schema/1.0.0/domain.d.ts +23 -0
  272. package/dist/v2/db/schema/1.0.0/domain.d.ts.map +1 -0
  273. package/dist/v2/db/schema/1.0.0/index.d.ts +1513 -0
  274. package/dist/v2/db/schema/1.0.0/index.d.ts.map +1 -0
  275. package/dist/v2/db/schema/1.0.0/subject.d.ts +23 -0
  276. package/dist/v2/db/schema/1.0.0/subject.d.ts.map +1 -0
  277. package/dist/v2/db/schema/index.cjs +326 -0
  278. package/dist/v2/db/schema/index.d.ts +1507 -0
  279. package/dist/v2/db/schema/index.d.ts.map +1 -0
  280. package/dist/v2/db/schema/index.js +241 -0
  281. package/dist/v2/define-config.cjs +36 -0
  282. package/dist/v2/define-config.d.ts +5 -0
  283. package/dist/v2/define-config.d.ts.map +1 -0
  284. package/dist/v2/define-config.js +2 -0
  285. package/dist/v2/handlers/consent/index.d.ts +260 -0
  286. package/dist/v2/handlers/consent/index.d.ts.map +1 -0
  287. package/dist/v2/handlers/consent/post.handler.d.ts +136 -0
  288. package/dist/v2/handlers/consent/post.handler.d.ts.map +1 -0
  289. package/dist/v2/handlers/consent/show-banner/geo.d.ts +10 -0
  290. package/dist/v2/handlers/consent/show-banner/geo.d.ts.map +1 -0
  291. package/dist/v2/handlers/consent/show-banner/geo.test.d.ts +2 -0
  292. package/dist/v2/handlers/consent/show-banner/geo.test.d.ts.map +1 -0
  293. package/dist/v2/handlers/consent/show-banner/handler.d.ts +71 -0
  294. package/dist/v2/handlers/consent/show-banner/handler.d.ts.map +1 -0
  295. package/dist/v2/handlers/consent/show-banner/handler.test.d.ts +2 -0
  296. package/dist/v2/handlers/consent/show-banner/handler.test.d.ts.map +1 -0
  297. package/dist/v2/handlers/consent/show-banner/translations.d.ts +13 -0
  298. package/dist/v2/handlers/consent/show-banner/translations.d.ts.map +1 -0
  299. package/dist/v2/handlers/consent/show-banner/translations.test.d.ts +2 -0
  300. package/dist/v2/handlers/consent/show-banner/translations.test.d.ts.map +1 -0
  301. package/dist/v2/handlers/consent/verify.handler.d.ts +103 -0
  302. package/dist/v2/handlers/consent/verify.handler.d.ts.map +1 -0
  303. package/dist/v2/handlers/meta/index.d.ts +19 -0
  304. package/dist/v2/handlers/meta/index.d.ts.map +1 -0
  305. package/dist/v2/handlers/meta/status.handler.d.ts +17 -0
  306. package/dist/v2/handlers/meta/status.handler.d.ts.map +1 -0
  307. package/dist/v2/init.d.ts +3 -0
  308. package/dist/v2/init.d.ts.map +1 -0
  309. package/dist/v2/init.test.d.ts +2 -0
  310. package/dist/v2/init.test.d.ts.map +1 -0
  311. package/dist/v2/middleware/cors/cors.d.ts +37 -0
  312. package/dist/v2/middleware/cors/cors.d.ts.map +1 -0
  313. package/dist/v2/middleware/cors/cors.test.d.ts +2 -0
  314. package/dist/v2/middleware/cors/cors.test.d.ts.map +1 -0
  315. package/dist/v2/middleware/cors/index.d.ts +30 -0
  316. package/dist/v2/middleware/cors/index.d.ts.map +1 -0
  317. package/dist/v2/middleware/cors/is-origin-trusted.d.ts +49 -0
  318. package/dist/v2/middleware/cors/is-origin-trusted.d.ts.map +1 -0
  319. package/dist/v2/middleware/cors/is-origin-trusted.test.d.ts +2 -0
  320. package/dist/v2/middleware/cors/is-origin-trusted.test.d.ts.map +1 -0
  321. package/dist/v2/middleware/cors/process-cors.d.ts +31 -0
  322. package/dist/v2/middleware/cors/process-cors.d.ts.map +1 -0
  323. package/dist/v2/middleware/openapi/config.d.ts +28 -0
  324. package/dist/v2/middleware/openapi/config.d.ts.map +1 -0
  325. package/dist/v2/middleware/openapi/handlers.d.ts +29 -0
  326. package/dist/v2/middleware/openapi/handlers.d.ts.map +1 -0
  327. package/dist/v2/middleware/openapi/index.d.ts +11 -0
  328. package/dist/v2/middleware/openapi/index.d.ts.map +1 -0
  329. package/dist/v2/middleware/process-ip/index.d.ts +3 -0
  330. package/dist/v2/middleware/process-ip/index.d.ts.map +1 -0
  331. package/dist/v2/router.cjs +1275 -0
  332. package/dist/v2/router.d.ts +280 -0
  333. package/dist/v2/router.d.ts.map +1 -0
  334. package/dist/v2/router.js +1231 -0
  335. package/dist/v2/types/api.d.ts +27 -0
  336. package/dist/v2/types/api.d.ts.map +1 -0
  337. package/dist/v2/types/index.cjs +40 -0
  338. package/dist/v2/types/index.d.ts +104 -0
  339. package/dist/v2/types/index.d.ts.map +1 -0
  340. package/dist/v2/types/index.js +6 -0
  341. package/dist/v2/utils/create-telemetry-options.d.ts +28 -0
  342. package/dist/v2/utils/create-telemetry-options.d.ts.map +1 -0
  343. package/dist/v2/utils/env.d.ts +60 -0
  344. package/dist/v2/utils/env.d.ts.map +1 -0
  345. package/dist/v2/utils/index.d.ts +3 -0
  346. package/dist/v2/utils/index.d.ts.map +1 -0
  347. package/dist/v2/utils/logger.d.ts +16 -0
  348. package/dist/v2/utils/logger.d.ts.map +1 -0
  349. package/dist/version.d.ts +1 -1
  350. package/package.json +106 -15
  351. package/readme.json +30 -0
  352. package/rslib.config.ts +13 -14
  353. package/src/__tests__/server.test.ts +1 -1
  354. package/src/contracts/consent/post.contract.test.ts +3 -8
  355. package/src/contracts/consent/post.contract.ts +13 -13
  356. package/src/contracts/consent/show-banner.contract.test.ts +9 -0
  357. package/src/contracts/consent/show-banner.contract.ts +2 -0
  358. package/src/contracts/consent/verify.contract.ts +19 -23
  359. package/src/core.ts +7 -0
  360. package/src/handlers/consent/show-banner/handler.ts +12 -9
  361. package/src/handlers/consent/show-banner/translations.ts +2 -2
  362. package/src/init.ts +9 -6
  363. package/src/middleware/openapi/index.ts +2 -2
  364. package/src/pkgs/api-router/hooks/__tests__/processor.test.ts +1 -1
  365. package/src/pkgs/data-model/fields/index.ts +17 -22
  366. package/src/pkgs/data-model/fields/zod-fields.ts +14 -26
  367. package/src/pkgs/data-model/hooks/index.ts +3 -2
  368. package/src/pkgs/data-model/index.ts +2 -4
  369. package/src/pkgs/data-model/schema/index.ts +6 -7
  370. package/src/pkgs/data-model/schema/schemas.ts +3 -3
  371. package/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts +4 -1
  372. package/src/pkgs/db-adapters/adapters/index.ts +2 -2
  373. package/src/pkgs/db-adapters/adapters/kysely-adapter/index.ts +4 -4
  374. package/src/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.ts +4 -5
  375. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/postgres.test.ts +2 -4
  376. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/sqlite.test.ts +2 -3
  377. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts +1 -6
  378. package/src/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.ts +4 -1
  379. package/src/pkgs/db-adapters/adapters/prisma-adapter/index.ts +1 -1
  380. package/src/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.ts +5 -2
  381. package/src/pkgs/db-adapters/index.ts +12 -13
  382. package/src/pkgs/migrations/get-migration.ts +4 -2
  383. package/src/pkgs/migrations/get-schema/get-schema.ts +0 -1
  384. package/src/pkgs/migrations/get-schema/process-fields.ts +1 -1
  385. package/src/pkgs/migrations/get-schema/process-tables.ts +0 -2
  386. package/src/pkgs/migrations/index.ts +7 -8
  387. package/src/pkgs/results/__tests__/error-codes.test.ts +2 -2
  388. package/src/pkgs/results/index.ts +22 -27
  389. package/src/pkgs/results/orpc-error-handler.ts +1 -1
  390. package/src/pkgs/results/results/result-helpers.ts +1 -1
  391. package/src/pkgs/types/index.ts +4 -4
  392. package/src/pkgs/types/options.ts +10 -3
  393. package/src/pkgs/utils/index.ts +1 -1
  394. package/src/pkgs/utils/logger.ts +1 -1
  395. package/src/schema/audit-log/schema.ts +3 -3
  396. package/src/schema/consent/schema.ts +4 -4
  397. package/src/schema/consent-policy/schema.ts +3 -3
  398. package/src/schema/consent-purpose/schema.ts +4 -4
  399. package/src/schema/consent-record/schema.ts +3 -3
  400. package/src/schema/definition.ts +1 -1
  401. package/src/schema/domain/schema.ts +5 -5
  402. package/src/schema/index.ts +14 -17
  403. package/src/schema/subject/schema.ts +3 -3
  404. package/src/schema/types.ts +1 -1
  405. package/src/testing/contract-testing.ts +15 -52
  406. package/src/types/index.ts +8 -8
  407. package/src/types/options.ts +2 -3
  408. package/src/v2/contracts/consent/index.test.ts +5 -0
  409. package/src/v2/contracts/consent/index.ts +9 -0
  410. package/src/v2/contracts/consent/post.contract.test.ts +521 -0
  411. package/src/v2/contracts/consent/post.contract.ts +155 -0
  412. package/src/v2/contracts/consent/show-banner.contract.test.ts +252 -0
  413. package/src/v2/contracts/consent/show-banner.contract.ts +73 -0
  414. package/src/v2/contracts/consent/verify.contract.test.ts +185 -0
  415. package/src/v2/contracts/consent/verify.contract.ts +122 -0
  416. package/src/v2/contracts/index.ts +20 -0
  417. package/src/v2/contracts/meta/index.test.ts +5 -0
  418. package/src/v2/contracts/meta/index.ts +5 -0
  419. package/src/v2/contracts/meta/status.contract.test.ts +226 -0
  420. package/src/v2/contracts/meta/status.contract.ts +34 -0
  421. package/src/v2/contracts/shared/jurisdiction.schema.ts +30 -0
  422. package/src/v2/contracts/test.utils.ts +400 -0
  423. package/src/v2/core.ts +379 -0
  424. package/src/v2/db/adapters/drizzle.ts +1 -0
  425. package/src/v2/db/adapters/index.ts +1 -0
  426. package/src/v2/db/adapters/kysely.ts +1 -0
  427. package/src/v2/db/adapters/mongo.ts +1 -0
  428. package/src/v2/db/adapters/prisma.ts +1 -0
  429. package/src/v2/db/adapters/typeorm.ts +1 -0
  430. package/src/v2/db/migrator/index.ts +80 -0
  431. package/src/v2/db/registry/audit-log.test.ts +77 -0
  432. package/src/v2/db/registry/audit-log.ts +46 -0
  433. package/src/v2/db/registry/consent-policy.test.ts +778 -0
  434. package/src/v2/db/registry/consent-policy.ts +74 -0
  435. package/src/v2/db/registry/consent-purpose.test.ts +485 -0
  436. package/src/v2/db/registry/consent-purpose.ts +41 -0
  437. package/src/v2/db/registry/consent.test.ts +843 -0
  438. package/src/v2/db/registry/consent.ts +42 -0
  439. package/src/v2/db/registry/domain.test.ts +463 -0
  440. package/src/v2/db/registry/domain.ts +51 -0
  441. package/src/v2/db/registry/index.ts +18 -0
  442. package/src/v2/db/registry/subject.test.ts +497 -0
  443. package/src/v2/db/registry/subject.ts +101 -0
  444. package/src/v2/db/registry/types.ts +10 -0
  445. package/src/v2/db/registry/utils/generate-id.test.ts +217 -0
  446. package/src/v2/db/registry/utils/generate-id.ts +134 -0
  447. package/src/v2/db/registry/utils.ts +134 -0
  448. package/src/v2/db/schema/1.0.0/audit-log.ts +32 -0
  449. package/src/v2/db/schema/1.0.0/consent-policy.ts +41 -0
  450. package/src/v2/db/schema/1.0.0/consent-purpose.ts +30 -0
  451. package/src/v2/db/schema/1.0.0/consent-record.ts +22 -0
  452. package/src/v2/db/schema/1.0.0/consent.ts +38 -0
  453. package/src/v2/db/schema/1.0.0/domain.ts +26 -0
  454. package/src/v2/db/schema/1.0.0/index.ts +56 -0
  455. package/src/v2/db/schema/1.0.0/subject.ts +26 -0
  456. package/src/v2/db/schema/index.ts +9 -0
  457. package/src/v2/define-config.ts +5 -0
  458. package/src/v2/handlers/consent/index.ts +9 -0
  459. package/src/v2/handlers/consent/post.handler.ts +254 -0
  460. package/src/v2/handlers/consent/show-banner/geo.test.ts +281 -0
  461. package/src/v2/handlers/consent/show-banner/geo.ts +96 -0
  462. package/src/v2/handlers/consent/show-banner/handler.test.ts +374 -0
  463. package/src/v2/handlers/consent/show-banner/handler.ts +123 -0
  464. package/src/v2/handlers/consent/show-banner/translations.test.ts +121 -0
  465. package/src/v2/handlers/consent/show-banner/translations.ts +79 -0
  466. package/src/v2/handlers/consent/verify.handler.ts +288 -0
  467. package/src/v2/handlers/meta/index.ts +5 -0
  468. package/src/v2/handlers/meta/status.handler.ts +43 -0
  469. package/src/v2/init.test.ts +114 -0
  470. package/src/v2/init.ts +126 -0
  471. package/src/v2/middleware/cors/cors.test.ts +111 -0
  472. package/src/v2/middleware/cors/cors.ts +192 -0
  473. package/src/v2/middleware/cors/index.ts +30 -0
  474. package/src/v2/middleware/cors/is-origin-trusted.test.ts +104 -0
  475. package/src/v2/middleware/cors/is-origin-trusted.ts +126 -0
  476. package/src/v2/middleware/cors/process-cors.ts +91 -0
  477. package/src/v2/middleware/openapi/config.ts +27 -0
  478. package/src/v2/middleware/openapi/handlers.ts +132 -0
  479. package/src/v2/middleware/openapi/index.ts +11 -0
  480. package/src/v2/middleware/process-ip/index.ts +39 -0
  481. package/src/v2/router.ts +8 -0
  482. package/src/v2/types/api.ts +32 -0
  483. package/src/v2/types/index.ts +121 -0
  484. package/src/v2/utils/create-telemetry-options.ts +115 -0
  485. package/src/v2/utils/env.ts +84 -0
  486. package/src/v2/utils/index.ts +2 -0
  487. package/src/v2/utils/logger.ts +38 -0
  488. package/src/version.ts +1 -1
  489. package/vitest.config.ts +11 -2
@@ -0,0 +1,778 @@
1
+ import { ORPCError } from '@orpc/server';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import type { ConsentPolicy, PolicyType } from '../schema';
4
+ import { policyRegistry } from './consent-policy';
5
+ import type { Registry } from './types';
6
+
7
+ describe('policyRegistry', () => {
8
+ const mockLogger = {
9
+ debug: vi.fn(),
10
+ error: vi.fn(),
11
+ info: vi.fn(),
12
+ warn: vi.fn(),
13
+ };
14
+
15
+ vi.mock('./utils/generate-id', () => ({
16
+ generateUniqueId: vi.fn().mockResolvedValue('pol_test'),
17
+ }));
18
+
19
+ /**
20
+ * Creates a mock consent policy object with the specified overrides
21
+ *
22
+ * @param overrides - Partial consent policy properties to override defaults
23
+ * @returns A complete ConsentPolicy object for testing
24
+ */
25
+ const createMockConsentPolicy = (
26
+ overrides: Partial<ConsentPolicy> = {}
27
+ ): ConsentPolicy => ({
28
+ id: 'pol_test',
29
+ version: '1.0.0',
30
+ type: 'privacy_policy',
31
+ name: 'privacy_policy',
32
+ effectiveDate: new Date('2024-01-01T00:00:00.000Z'),
33
+ expirationDate: null,
34
+ content:
35
+ '[PLACEHOLDER] This is an automatically generated version of the privacy_policy policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: 2024-01-01T00:00:00.000Z',
36
+ contentHash: 'test_hash_123',
37
+ isActive: true,
38
+ createdAt: new Date('2024-01-01T00:00:00.000Z'),
39
+ ...overrides,
40
+ });
41
+
42
+ /**
43
+ * Mock implementation of crypto.subtle.digest for testing
44
+ * Returns a predictable hash for consistent testing
45
+ */
46
+ const mockCryptoSubtle = {
47
+ digest: vi.fn().mockResolvedValue(
48
+ new ArrayBuffer(32) // SHA-256 produces 32 bytes
49
+ ),
50
+ };
51
+
52
+ // Mock the global crypto object
53
+ beforeEach(() => {
54
+ // Reset the mock to return zeros for predictable hash
55
+ const mockArrayBuffer = new ArrayBuffer(32);
56
+ const view = new Uint8Array(mockArrayBuffer);
57
+ view.fill(0); // Fill with zeros for predictable hash "0000..."
58
+ mockCryptoSubtle.digest.mockResolvedValue(mockArrayBuffer);
59
+
60
+ // Mock the crypto.subtle.digest method using vitest spy
61
+ vi.stubGlobal('crypto', {
62
+ subtle: mockCryptoSubtle,
63
+ });
64
+ });
65
+
66
+ afterEach(() => {
67
+ vi.clearAllMocks();
68
+ vi.unstubAllGlobals();
69
+ });
70
+
71
+ describe('findConsentPolicyById', () => {
72
+ it('should return policy when found by id', async () => {
73
+ const mockPolicy = createMockConsentPolicy({
74
+ id: 'pol_specific_123',
75
+ type: 'cookie_banner',
76
+ });
77
+
78
+ const db = {
79
+ findFirst: vi.fn().mockResolvedValue(mockPolicy),
80
+ };
81
+
82
+ const registry = policyRegistry({
83
+ db,
84
+ ctx: { logger: mockLogger },
85
+ } as unknown as Registry);
86
+
87
+ const result = await registry.findConsentPolicyById('pol_specific_123');
88
+
89
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
90
+ where: expect.any(Function),
91
+ });
92
+
93
+ expect(result).toEqual(mockPolicy);
94
+ });
95
+
96
+ it('should return null when policy not found by id', async () => {
97
+ const db = {
98
+ findFirst: vi.fn().mockResolvedValue(null),
99
+ };
100
+
101
+ const registry = policyRegistry({
102
+ db,
103
+ ctx: { logger: mockLogger },
104
+ } as unknown as Registry);
105
+
106
+ const result = await registry.findConsentPolicyById('nonexistent_id');
107
+
108
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
109
+ where: expect.any(Function),
110
+ });
111
+
112
+ expect(result).toBeNull();
113
+ });
114
+
115
+ it('should handle various policy id formats', async () => {
116
+ const testIds = [
117
+ 'pol_123',
118
+ 'policy_test_long_id_name',
119
+ 'SHORT',
120
+ 'ID_WITH_UNDERSCORES',
121
+ 'mixed.Case-id_123',
122
+ ];
123
+
124
+ for (const testId of testIds) {
125
+ const mockPolicy = createMockConsentPolicy({ id: testId });
126
+
127
+ const db = {
128
+ findFirst: vi.fn().mockResolvedValue(mockPolicy),
129
+ };
130
+
131
+ const registry = policyRegistry({
132
+ db,
133
+ ctx: { logger: mockLogger },
134
+ } as unknown as Registry);
135
+
136
+ const result = await registry.findConsentPolicyById(testId);
137
+
138
+ expect(result?.id).toBe(testId);
139
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
140
+ where: expect.any(Function),
141
+ });
142
+
143
+ vi.clearAllMocks();
144
+ }
145
+ });
146
+
147
+ it('should propagate database errors', async () => {
148
+ const dbError = new Error('Database connection failed');
149
+ const db = {
150
+ findFirst: vi.fn().mockRejectedValue(dbError),
151
+ };
152
+
153
+ const registry = policyRegistry({
154
+ db,
155
+ ctx: { logger: mockLogger },
156
+ } as unknown as Registry);
157
+
158
+ const promise = registry.findConsentPolicyById('error_id');
159
+
160
+ await expect(promise).rejects.toThrow('Database connection failed');
161
+ });
162
+ });
163
+
164
+ describe('findOrCreatePolicy', () => {
165
+ describe('when policy exists', () => {
166
+ it('should return existing active policy for given type', async () => {
167
+ const mockPolicy = createMockConsentPolicy({
168
+ type: 'terms_and_conditions',
169
+ version: '2.1.0',
170
+ isActive: true,
171
+ });
172
+
173
+ const db = {
174
+ findFirst: vi.fn().mockResolvedValue(mockPolicy),
175
+ create: vi.fn(),
176
+ };
177
+
178
+ const registry = policyRegistry({
179
+ db,
180
+ ctx: { logger: mockLogger },
181
+ } as unknown as Registry);
182
+
183
+ const result = await registry.findOrCreatePolicy(
184
+ 'terms_and_conditions'
185
+ );
186
+
187
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
188
+ where: expect.any(Function),
189
+ orderBy: ['effectiveDate', 'desc'],
190
+ });
191
+
192
+ expect(db.create).not.toHaveBeenCalled();
193
+ expect(result).toEqual(mockPolicy);
194
+ expect(mockLogger.debug).toHaveBeenCalledWith('Found existing policy', {
195
+ type: 'terms_and_conditions',
196
+ policyId: mockPolicy.id,
197
+ });
198
+ });
199
+
200
+ it('should handle all valid policy types', async () => {
201
+ const validPolicyTypes: PolicyType[] = [
202
+ 'cookie_banner',
203
+ 'privacy_policy',
204
+ 'dpa',
205
+ 'terms_and_conditions',
206
+ 'marketing_communications',
207
+ 'age_verification',
208
+ 'other',
209
+ ];
210
+
211
+ for (const policyType of validPolicyTypes) {
212
+ const mockPolicy = createMockConsentPolicy({
213
+ type: policyType,
214
+ name: policyType,
215
+ });
216
+
217
+ const db = {
218
+ findFirst: vi.fn().mockResolvedValue(mockPolicy),
219
+ create: vi.fn(),
220
+ };
221
+
222
+ const registry = policyRegistry({
223
+ db,
224
+ ctx: { logger: mockLogger },
225
+ } as unknown as Registry);
226
+
227
+ const result = await registry.findOrCreatePolicy(policyType);
228
+
229
+ expect(result.type).toBe(policyType);
230
+ expect(result.name).toBe(policyType);
231
+ expect(db.create).not.toHaveBeenCalled();
232
+
233
+ vi.clearAllMocks();
234
+ }
235
+ });
236
+
237
+ it('should return most recent active policy when multiple exist', async () => {
238
+ const mostRecentPolicy = createMockConsentPolicy({
239
+ id: 'pol_most_recent',
240
+ effectiveDate: new Date('2024-03-01T00:00:00.000Z'),
241
+ version: '3.0.0',
242
+ });
243
+
244
+ const db = {
245
+ findFirst: vi.fn().mockResolvedValue(mostRecentPolicy),
246
+ create: vi.fn(),
247
+ };
248
+
249
+ const registry = policyRegistry({
250
+ db,
251
+ ctx: { logger: mockLogger },
252
+ } as unknown as Registry);
253
+
254
+ const result = await registry.findOrCreatePolicy('privacy_policy');
255
+
256
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
257
+ where: expect.any(Function),
258
+ orderBy: ['effectiveDate', 'desc'],
259
+ });
260
+
261
+ expect(result).toEqual(mostRecentPolicy);
262
+ expect(result.id).toBe('pol_most_recent');
263
+ });
264
+ });
265
+
266
+ describe('when policy does not exist', () => {
267
+ it('should create new policy with placeholder content', async () => {
268
+ const fakeDate = new Date('2024-01-15T10:30:00.000Z');
269
+ vi.useFakeTimers();
270
+ vi.setSystemTime(fakeDate);
271
+
272
+ const newMockPolicy = createMockConsentPolicy({
273
+ id: 'pol_test',
274
+ type: 'dpa',
275
+ name: 'dpa',
276
+ effectiveDate: fakeDate,
277
+ content: `[PLACEHOLDER] This is an automatically generated version of the dpa policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: ${fakeDate.toISOString()}`,
278
+ contentHash:
279
+ '0000000000000000000000000000000000000000000000000000000000000000',
280
+ });
281
+
282
+ const db = {
283
+ findFirst: vi.fn().mockResolvedValue(null),
284
+ create: vi.fn().mockResolvedValue(newMockPolicy),
285
+ };
286
+
287
+ const registry = policyRegistry({
288
+ db,
289
+ ctx: { logger: mockLogger },
290
+ } as unknown as Registry);
291
+
292
+ const result = await registry.findOrCreatePolicy('dpa');
293
+
294
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
295
+ where: expect.any(Function),
296
+ orderBy: ['effectiveDate', 'desc'],
297
+ });
298
+
299
+ expect(db.create).toHaveBeenCalledWith('consentPolicy', {
300
+ id: 'pol_test',
301
+ version: '1.0.0',
302
+ type: 'dpa',
303
+ name: 'dpa',
304
+ effectiveDate: fakeDate,
305
+ content: `[PLACEHOLDER] This is an automatically generated version of the dpa policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: ${fakeDate.toISOString()}`,
306
+ contentHash:
307
+ '0000000000000000000000000000000000000000000000000000000000000000',
308
+ isActive: true,
309
+ expirationDate: null,
310
+ });
311
+
312
+ expect(result).toEqual(newMockPolicy);
313
+
314
+ vi.useRealTimers();
315
+ });
316
+
317
+ it('should create policies for all valid types with correct defaults', async () => {
318
+ const validPolicyTypes: PolicyType[] = [
319
+ 'cookie_banner',
320
+ 'privacy_policy',
321
+ 'dpa',
322
+ 'terms_and_conditions',
323
+ 'marketing_communications',
324
+ 'age_verification',
325
+ 'other',
326
+ ];
327
+
328
+ const fakeDate = new Date('2024-02-01T00:00:00.000Z');
329
+ vi.useFakeTimers();
330
+ vi.setSystemTime(fakeDate);
331
+
332
+ for (const policyType of validPolicyTypes) {
333
+ const mockPolicy = createMockConsentPolicy({
334
+ type: policyType,
335
+ name: policyType,
336
+ effectiveDate: fakeDate,
337
+ });
338
+
339
+ const db = {
340
+ findFirst: vi.fn().mockResolvedValue(null),
341
+ create: vi.fn().mockResolvedValue(mockPolicy),
342
+ };
343
+
344
+ const registry = policyRegistry({
345
+ db,
346
+ ctx: { logger: mockLogger },
347
+ } as unknown as Registry);
348
+
349
+ const result = await registry.findOrCreatePolicy(policyType);
350
+
351
+ expect(db.create).toHaveBeenCalledWith('consentPolicy', {
352
+ id: 'pol_test',
353
+ version: '1.0.0',
354
+ type: policyType,
355
+ name: policyType,
356
+ effectiveDate: fakeDate,
357
+ content: expect.stringContaining(
358
+ `[PLACEHOLDER] This is an automatically generated version of the ${policyType} policy.`
359
+ ),
360
+ contentHash: expect.any(String),
361
+ isActive: true,
362
+ expirationDate: null,
363
+ });
364
+
365
+ expect(result.type).toBe(policyType);
366
+ expect(result.name).toBe(policyType);
367
+ expect(result.version).toBe('1.0.0');
368
+ expect(result.isActive).toBe(true);
369
+ expect(result.expirationDate).toBeNull();
370
+
371
+ vi.clearAllMocks();
372
+ }
373
+
374
+ vi.useRealTimers();
375
+ });
376
+
377
+ it('should generate correct placeholder content structure', async () => {
378
+ const fakeDate = new Date('2024-06-15T14:30:45.123Z');
379
+ vi.useFakeTimers();
380
+ vi.setSystemTime(fakeDate);
381
+
382
+ const mockPolicy = createMockConsentPolicy({
383
+ type: 'marketing_communications',
384
+ content: `[PLACEHOLDER] This is an automatically generated version of the marketing_communications policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: ${fakeDate.toISOString()}`,
385
+ });
386
+
387
+ const db = {
388
+ findFirst: vi.fn().mockResolvedValue(null),
389
+ create: vi.fn().mockResolvedValue(mockPolicy),
390
+ };
391
+
392
+ const registry = policyRegistry({
393
+ db,
394
+ ctx: { logger: mockLogger },
395
+ } as unknown as Registry);
396
+
397
+ await registry.findOrCreatePolicy('marketing_communications');
398
+
399
+ const createCall = db.create.mock.calls[0]?.[1];
400
+ expect(createCall?.content).toBe(
401
+ `[PLACEHOLDER] This is an automatically generated version of the marketing_communications policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: ${fakeDate.toISOString()}`
402
+ );
403
+
404
+ expect(createCall?.content).toContain('[PLACEHOLDER]');
405
+ expect(createCall?.content).toContain(
406
+ 'marketing_communications policy'
407
+ );
408
+ expect(createCall?.content).toContain(fakeDate.toISOString());
409
+
410
+ vi.useRealTimers();
411
+ });
412
+ });
413
+
414
+ describe('content hash generation', () => {
415
+ it('should generate SHA-256 hash of policy content', async () => {
416
+ const testContent = 'Test policy content for hashing';
417
+ const expectedHash =
418
+ '0000000000000000000000000000000000000000000000000000000000000000';
419
+
420
+ const mockPolicy = createMockConsentPolicy({
421
+ content: testContent,
422
+ contentHash: expectedHash,
423
+ });
424
+
425
+ const db = {
426
+ findFirst: vi.fn().mockResolvedValue(null),
427
+ create: vi.fn().mockResolvedValue(mockPolicy),
428
+ };
429
+
430
+ const registry = policyRegistry({
431
+ db,
432
+ ctx: { logger: mockLogger },
433
+ } as unknown as Registry);
434
+
435
+ await registry.findOrCreatePolicy('privacy_policy');
436
+
437
+ expect(mockCryptoSubtle.digest).toHaveBeenCalledWith(
438
+ 'SHA-256',
439
+ expect.any(Uint8Array)
440
+ );
441
+
442
+ const createCall = db.create.mock.calls[0]?.[1];
443
+ expect(createCall?.contentHash).toBe(expectedHash);
444
+ });
445
+
446
+ it('should handle different content producing different hashes', async () => {
447
+ // Mock different hash results for different content
448
+ const hash1Buffer = new ArrayBuffer(32);
449
+ const hash1View = new Uint8Array(hash1Buffer);
450
+ hash1View.fill(1);
451
+
452
+ const hash2Buffer = new ArrayBuffer(32);
453
+ const hash2View = new Uint8Array(hash2Buffer);
454
+ hash2View.fill(2);
455
+
456
+ mockCryptoSubtle.digest
457
+ .mockResolvedValueOnce(hash1Buffer)
458
+ .mockResolvedValueOnce(hash2Buffer);
459
+
460
+ const policy1 = createMockConsentPolicy({
461
+ type: 'privacy_policy',
462
+ contentHash:
463
+ '0101010101010101010101010101010101010101010101010101010101010101',
464
+ });
465
+
466
+ const policy2 = createMockConsentPolicy({
467
+ type: 'cookie_banner',
468
+ contentHash:
469
+ '0202020202020202020202020202020202020202020202020202020202020202',
470
+ });
471
+
472
+ const db = {
473
+ findFirst: vi.fn().mockResolvedValue(null),
474
+ create: vi
475
+ .fn()
476
+ .mockResolvedValueOnce(policy1)
477
+ .mockResolvedValueOnce(policy2),
478
+ };
479
+
480
+ const registry = policyRegistry({
481
+ db,
482
+ ctx: { logger: mockLogger },
483
+ } as unknown as Registry);
484
+
485
+ await registry.findOrCreatePolicy('privacy_policy');
486
+ await registry.findOrCreatePolicy('cookie_banner');
487
+
488
+ const call1 = db.create.mock.calls[0]?.[1];
489
+ const call2 = db.create.mock.calls[1]?.[1];
490
+
491
+ expect(call1?.contentHash).toBe(
492
+ '0101010101010101010101010101010101010101010101010101010101010101'
493
+ );
494
+ expect(call2?.contentHash).toBe(
495
+ '0202020202020202020202020202020202020202020202020202020202020202'
496
+ );
497
+ expect(call1?.contentHash).not.toBe(call2?.contentHash);
498
+ });
499
+ });
500
+
501
+ describe('error handling', () => {
502
+ it('should throw ORPCError when crypto.subtle.digest fails', async () => {
503
+ const cryptoError = new Error('Crypto operation failed');
504
+ mockCryptoSubtle.digest.mockRejectedValue(cryptoError);
505
+
506
+ const db = {
507
+ findFirst: vi.fn().mockResolvedValue(null),
508
+ create: vi.fn(),
509
+ };
510
+
511
+ const registry = policyRegistry({
512
+ db,
513
+ ctx: { logger: mockLogger },
514
+ } as unknown as Registry);
515
+
516
+ const promise = registry.findOrCreatePolicy('privacy_policy');
517
+
518
+ await expect(promise).rejects.toBeInstanceOf(ORPCError);
519
+ await expect(promise).rejects.toEqual(
520
+ expect.objectContaining({
521
+ message: 'Failed to generate policy content hash',
522
+ code: 'POLICY_CREATION_FAILED',
523
+ status: 500,
524
+ data: { name: 'privacy_policy' },
525
+ })
526
+ );
527
+
528
+ expect(db.create).not.toHaveBeenCalled();
529
+ });
530
+
531
+ it('should handle crypto errors with non-Error objects', async () => {
532
+ const cryptoError = 'String error message';
533
+ mockCryptoSubtle.digest.mockRejectedValue(cryptoError);
534
+
535
+ const db = {
536
+ findFirst: vi.fn().mockResolvedValue(null),
537
+ create: vi.fn(),
538
+ };
539
+
540
+ const registry = policyRegistry({
541
+ db,
542
+ ctx: { logger: mockLogger },
543
+ } as unknown as Registry);
544
+
545
+ const promise = registry.findOrCreatePolicy('privacy_policy');
546
+
547
+ await expect(promise).rejects.toBeInstanceOf(ORPCError);
548
+ await expect(promise).rejects.toEqual(
549
+ expect.objectContaining({
550
+ message: 'Failed to generate policy content hash',
551
+ code: 'POLICY_CREATION_FAILED',
552
+ status: 500,
553
+ data: { name: 'privacy_policy' },
554
+ })
555
+ );
556
+
557
+ const error = await promise.catch((e) => e);
558
+ expect(error).toEqual(
559
+ expect.objectContaining({
560
+ code: 'POLICY_CREATION_FAILED',
561
+ status: 500,
562
+ data: { name: 'privacy_policy' },
563
+ })
564
+ );
565
+ });
566
+
567
+ it('should propagate database findFirst errors', async () => {
568
+ const dbError = new Error('Database query failed');
569
+ const db = {
570
+ findFirst: vi.fn().mockRejectedValue(dbError),
571
+ };
572
+
573
+ const registry = policyRegistry({
574
+ db,
575
+ ctx: { logger: mockLogger },
576
+ } as unknown as Registry);
577
+
578
+ const promise = registry.findOrCreatePolicy('privacy_policy');
579
+
580
+ await expect(promise).rejects.toThrow('Database query failed');
581
+ });
582
+
583
+ it('should propagate database create errors', async () => {
584
+ const dbError = new Error('Create operation failed');
585
+ const db = {
586
+ findFirst: vi.fn().mockResolvedValue(null),
587
+ create: vi.fn().mockRejectedValue(dbError),
588
+ };
589
+
590
+ const registry = policyRegistry({
591
+ db,
592
+ ctx: { logger: mockLogger },
593
+ } as unknown as Registry);
594
+
595
+ const promise = registry.findOrCreatePolicy('privacy_policy');
596
+
597
+ await expect(promise).rejects.toThrow('Create operation failed');
598
+ });
599
+ });
600
+ });
601
+
602
+ describe('database query construction', () => {
603
+ it('should construct correct query for policy lookup by id', async () => {
604
+ const db = {
605
+ findFirst: vi.fn().mockResolvedValue(null),
606
+ };
607
+
608
+ const registry = policyRegistry({
609
+ db,
610
+ ctx: { logger: mockLogger },
611
+ } as unknown as Registry);
612
+
613
+ await registry.findConsentPolicyById('test_id');
614
+
615
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
616
+ where: expect.any(Function),
617
+ });
618
+
619
+ const whereCall = db.findFirst.mock.calls[0]?.[1];
620
+ expect(whereCall).toHaveProperty('where');
621
+ expect(typeof whereCall?.where).toBe('function');
622
+ });
623
+
624
+ it('should construct correct query for active policy lookup by type', async () => {
625
+ const db = {
626
+ findFirst: vi.fn().mockResolvedValue(null),
627
+ create: vi.fn().mockResolvedValue(createMockConsentPolicy()),
628
+ };
629
+
630
+ const registry = policyRegistry({
631
+ db,
632
+ ctx: { logger: mockLogger },
633
+ } as unknown as Registry);
634
+
635
+ await registry.findOrCreatePolicy('privacy_policy');
636
+
637
+ expect(db.findFirst).toHaveBeenCalledWith('consentPolicy', {
638
+ where: expect.any(Function),
639
+ orderBy: ['effectiveDate', 'desc'],
640
+ });
641
+
642
+ const findCall = db.findFirst.mock.calls[0]?.[1];
643
+ expect(findCall).toHaveProperty('where');
644
+ expect(findCall).toHaveProperty('orderBy');
645
+ expect(findCall?.orderBy).toEqual(['effectiveDate', 'desc']);
646
+ });
647
+ });
648
+
649
+ describe('edge cases', () => {
650
+ it('should handle concurrent policy creation requests', async () => {
651
+ const fakeDate = new Date('2024-01-01T00:00:00.000Z');
652
+ vi.useFakeTimers();
653
+ vi.setSystemTime(fakeDate);
654
+
655
+ const mockPolicy = createMockConsentPolicy({
656
+ type: 'privacy_policy',
657
+ effectiveDate: fakeDate,
658
+ });
659
+
660
+ const db = {
661
+ findFirst: vi.fn().mockResolvedValue(null),
662
+ create: vi.fn().mockResolvedValue(mockPolicy),
663
+ };
664
+
665
+ const registry = policyRegistry({
666
+ db,
667
+ ctx: { logger: mockLogger },
668
+ } as unknown as Registry);
669
+
670
+ // Simulate concurrent requests
671
+ const promises = [
672
+ registry.findOrCreatePolicy('privacy_policy'),
673
+ registry.findOrCreatePolicy('privacy_policy'),
674
+ registry.findOrCreatePolicy('privacy_policy'),
675
+ ];
676
+
677
+ const results = await Promise.all(promises);
678
+
679
+ // All should succeed (actual uniqueness would be handled by database constraints)
680
+ expect(results).toHaveLength(3);
681
+ for (const result of results) {
682
+ expect(result.type).toBe('privacy_policy');
683
+ }
684
+
685
+ expect(db.create).toHaveBeenCalledTimes(3);
686
+
687
+ vi.useRealTimers();
688
+ });
689
+
690
+ it('should handle very long policy type names in content generation', async () => {
691
+ const longPolicyType =
692
+ 'very_long_policy_type_name_that_might_cause_issues' as PolicyType;
693
+
694
+ const mockPolicy = createMockConsentPolicy({
695
+ type: longPolicyType,
696
+ name: longPolicyType,
697
+ });
698
+
699
+ const db = {
700
+ findFirst: vi.fn().mockResolvedValue(null),
701
+ create: vi.fn().mockResolvedValue(mockPolicy),
702
+ };
703
+
704
+ const registry = policyRegistry({
705
+ db,
706
+ ctx: { logger: mockLogger },
707
+ } as unknown as Registry);
708
+
709
+ const result = await registry.findOrCreatePolicy(longPolicyType);
710
+
711
+ expect(result.type).toBe(longPolicyType);
712
+ expect(result.name).toBe(longPolicyType);
713
+
714
+ const createCall = db.create.mock.calls[0]?.[1];
715
+ expect(createCall?.content).toContain(longPolicyType);
716
+ });
717
+
718
+ it('should handle Unix epoch date in content generation', async () => {
719
+ const edgeDate = new Date('1970-01-01T00:00:00.000Z');
720
+ vi.useFakeTimers();
721
+ vi.setSystemTime(edgeDate);
722
+
723
+ const mockPolicy = createMockConsentPolicy({
724
+ effectiveDate: edgeDate,
725
+ });
726
+
727
+ const db = {
728
+ findFirst: vi.fn().mockResolvedValue(null),
729
+ create: vi.fn().mockResolvedValue(mockPolicy),
730
+ };
731
+
732
+ const registry = policyRegistry({
733
+ db,
734
+ ctx: { logger: mockLogger },
735
+ } as unknown as Registry);
736
+
737
+ const result = await registry.findOrCreatePolicy('privacy_policy');
738
+
739
+ expect(result.effectiveDate).toEqual(edgeDate);
740
+
741
+ const createCall = db.create.mock.calls[0]?.[1];
742
+ expect(createCall?.content).toContain(edgeDate.toISOString());
743
+ expect(createCall?.effectiveDate).toEqual(edgeDate);
744
+
745
+ vi.useRealTimers();
746
+ });
747
+
748
+ it('should handle leap year date in content generation', async () => {
749
+ const edgeDate = new Date('2024-02-29T23:59:59.999Z');
750
+ vi.useFakeTimers();
751
+ vi.setSystemTime(edgeDate);
752
+
753
+ const mockPolicy = createMockConsentPolicy({
754
+ effectiveDate: edgeDate,
755
+ });
756
+
757
+ const db = {
758
+ findFirst: vi.fn().mockResolvedValue(null),
759
+ create: vi.fn().mockResolvedValue(mockPolicy),
760
+ };
761
+
762
+ const registry = policyRegistry({
763
+ db,
764
+ ctx: { logger: mockLogger },
765
+ } as unknown as Registry);
766
+
767
+ const result = await registry.findOrCreatePolicy('privacy_policy');
768
+
769
+ expect(result.effectiveDate).toEqual(edgeDate);
770
+
771
+ const createCall = db.create.mock.calls[0]?.[1];
772
+ expect(createCall?.content).toContain(edgeDate.toISOString());
773
+ expect(createCall?.effectiveDate).toEqual(edgeDate);
774
+
775
+ vi.useRealTimers();
776
+ });
777
+ });
778
+ });