@c15t/backend 1.0.5 → 1.2.0-canary.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 (462) hide show
  1. package/.turbo/turbo-build.log +33 -39
  2. package/.turbo/turbo-fmt.log +3 -3
  3. package/.turbo/turbo-test.log +531 -0
  4. package/coverage/coverage-final.json +84 -0
  5. package/coverage/coverage-summary.json +85 -0
  6. package/coverage/html/backend/index.html +116 -0
  7. package/coverage/html/backend/rslib.config.ts.html +415 -0
  8. package/coverage/html/backend/src/contracts/consent/index.html +161 -0
  9. package/coverage/html/backend/src/contracts/consent/index.ts.html +112 -0
  10. package/coverage/html/backend/src/contracts/consent/post.contract.ts.html +559 -0
  11. package/coverage/html/backend/src/contracts/consent/show-banner.contract.ts.html +220 -0
  12. package/coverage/html/backend/src/contracts/consent/verify.contract.ts.html +463 -0
  13. package/coverage/html/backend/src/contracts/index.html +116 -0
  14. package/coverage/html/backend/src/contracts/index.ts.html +139 -0
  15. package/coverage/html/backend/src/contracts/meta/index.html +131 -0
  16. package/coverage/html/backend/src/contracts/meta/index.ts.html +100 -0
  17. package/coverage/html/backend/src/contracts/meta/status.contract.ts.html +196 -0
  18. package/coverage/html/backend/src/contracts/shared/index.html +116 -0
  19. package/coverage/html/backend/src/contracts/shared/jurisdiction.schema.ts.html +175 -0
  20. package/coverage/html/backend/src/core.ts.html +1624 -0
  21. package/coverage/html/backend/src/handlers/consent/index.html +161 -0
  22. package/coverage/html/backend/src/handlers/consent/index.ts.html +112 -0
  23. package/coverage/html/backend/src/handlers/consent/post.handler.ts.html +889 -0
  24. package/coverage/html/backend/src/handlers/consent/show-banner.handler.ts.html +535 -0
  25. package/coverage/html/backend/src/handlers/consent/verify.handler.ts.html +1000 -0
  26. package/coverage/html/backend/src/handlers/meta/index.html +131 -0
  27. package/coverage/html/backend/src/handlers/meta/index.ts.html +100 -0
  28. package/coverage/html/backend/src/handlers/meta/status.handler.ts.html +226 -0
  29. package/coverage/html/backend/src/index.html +161 -0
  30. package/coverage/html/backend/src/init.ts.html +1018 -0
  31. package/coverage/html/backend/src/pkgs/api-router/hooks/index.html +116 -0
  32. package/coverage/html/backend/src/pkgs/api-router/hooks/processor.ts.html +544 -0
  33. package/coverage/html/backend/src/pkgs/api-router/index.html +116 -0
  34. package/coverage/html/backend/src/pkgs/api-router/telemetry.ts.html +334 -0
  35. package/coverage/html/backend/src/pkgs/api-router/utils/cors.ts.html +304 -0
  36. package/coverage/html/backend/src/pkgs/api-router/utils/index.html +131 -0
  37. package/coverage/html/backend/src/pkgs/api-router/utils/ip.ts.html +361 -0
  38. package/coverage/html/backend/src/pkgs/data-model/fields/field-factory.ts.html +709 -0
  39. package/coverage/html/backend/src/pkgs/data-model/fields/id-generator.ts.html +256 -0
  40. package/coverage/html/backend/src/pkgs/data-model/fields/index.html +161 -0
  41. package/coverage/html/backend/src/pkgs/data-model/fields/superjson-utils.ts.html +136 -0
  42. package/coverage/html/backend/src/pkgs/data-model/fields/zod-fields.ts.html +496 -0
  43. package/coverage/html/backend/src/pkgs/data-model/hooks/create-hooks.ts.html +349 -0
  44. package/coverage/html/backend/src/pkgs/data-model/hooks/index.html +176 -0
  45. package/coverage/html/backend/src/pkgs/data-model/hooks/update-hooks.ts.html +358 -0
  46. package/coverage/html/backend/src/pkgs/data-model/hooks/update-many-hooks.ts.html +613 -0
  47. package/coverage/html/backend/src/pkgs/data-model/hooks/utils.ts.html +538 -0
  48. package/coverage/html/backend/src/pkgs/data-model/hooks/with-hooks-factory.ts.html +289 -0
  49. package/coverage/html/backend/src/pkgs/db-adapters/adapter-factory.ts.html +289 -0
  50. package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts.html +2203 -0
  51. package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/index.html +116 -0
  52. package/coverage/html/backend/src/pkgs/db-adapters/adapters/index.html +116 -0
  53. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/dialect.ts.html +670 -0
  54. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/index.html +131 -0
  55. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.ts.html +3634 -0
  56. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/index.html +116 -0
  57. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts.html +1417 -0
  58. package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/index.html +116 -0
  59. package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.ts.html +2071 -0
  60. package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/index.html +116 -0
  61. package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.ts.html +1834 -0
  62. package/coverage/html/backend/src/pkgs/db-adapters/adapters/test.ts.html +316 -0
  63. package/coverage/html/backend/src/pkgs/db-adapters/index.html +131 -0
  64. package/coverage/html/backend/src/pkgs/db-adapters/utils.ts.html +238 -0
  65. package/coverage/html/backend/src/pkgs/migrations/get-migration.ts.html +343 -0
  66. package/coverage/html/backend/src/pkgs/migrations/get-schema/get-schema.ts.html +217 -0
  67. package/coverage/html/backend/src/pkgs/migrations/get-schema/index.html +146 -0
  68. package/coverage/html/backend/src/pkgs/migrations/get-schema/process-fields.ts.html +280 -0
  69. package/coverage/html/backend/src/pkgs/migrations/get-schema/process-tables.ts.html +289 -0
  70. package/coverage/html/backend/src/pkgs/migrations/index.html +176 -0
  71. package/coverage/html/backend/src/pkgs/migrations/migration-builders.ts.html +595 -0
  72. package/coverage/html/backend/src/pkgs/migrations/migration-execution.ts.html +301 -0
  73. package/coverage/html/backend/src/pkgs/migrations/schema-comparison.ts.html +694 -0
  74. package/coverage/html/backend/src/pkgs/migrations/type-mapping.ts.html +817 -0
  75. package/coverage/html/backend/src/pkgs/results/core/error-class.ts.html +976 -0
  76. package/coverage/html/backend/src/pkgs/results/core/error-codes.ts.html +703 -0
  77. package/coverage/html/backend/src/pkgs/results/core/index.html +146 -0
  78. package/coverage/html/backend/src/pkgs/results/core/tracing.ts.html +280 -0
  79. package/coverage/html/backend/src/pkgs/results/create-telemetry-options.ts.html +271 -0
  80. package/coverage/html/backend/src/pkgs/results/index.html +131 -0
  81. package/coverage/html/backend/src/pkgs/results/orpc-error-handler.ts.html +496 -0
  82. package/coverage/html/backend/src/pkgs/results/results/index.html +131 -0
  83. package/coverage/html/backend/src/pkgs/results/results/recovery-utils.ts.html +628 -0
  84. package/coverage/html/backend/src/pkgs/results/results/result-helpers.ts.html +1234 -0
  85. package/coverage/html/backend/src/pkgs/utils/env.ts.html +337 -0
  86. package/coverage/html/backend/src/pkgs/utils/index.html +146 -0
  87. package/coverage/html/backend/src/pkgs/utils/logger.ts.html +199 -0
  88. package/coverage/html/backend/src/pkgs/utils/url.ts.html +400 -0
  89. package/coverage/html/backend/src/router.ts.html +109 -0
  90. package/coverage/html/backend/src/schema/audit-log/index.html +146 -0
  91. package/coverage/html/backend/src/schema/audit-log/registry.ts.html +436 -0
  92. package/coverage/html/backend/src/schema/audit-log/schema.ts.html +223 -0
  93. package/coverage/html/backend/src/schema/audit-log/table.ts.html +640 -0
  94. package/coverage/html/backend/src/schema/consent/index.html +146 -0
  95. package/coverage/html/backend/src/schema/consent/registry.ts.html +616 -0
  96. package/coverage/html/backend/src/schema/consent/schema.ts.html +238 -0
  97. package/coverage/html/backend/src/schema/consent/table.ts.html +748 -0
  98. package/coverage/html/backend/src/schema/consent-policy/index.html +146 -0
  99. package/coverage/html/backend/src/schema/consent-policy/registry.ts.html +1063 -0
  100. package/coverage/html/backend/src/schema/consent-policy/schema.ts.html +265 -0
  101. package/coverage/html/backend/src/schema/consent-policy/table.ts.html +535 -0
  102. package/coverage/html/backend/src/schema/consent-purpose/index.html +146 -0
  103. package/coverage/html/backend/src/schema/consent-purpose/registry.ts.html +589 -0
  104. package/coverage/html/backend/src/schema/consent-purpose/schema.ts.html +259 -0
  105. package/coverage/html/backend/src/schema/consent-purpose/table.ts.html +547 -0
  106. package/coverage/html/backend/src/schema/consent-record/index.html +131 -0
  107. package/coverage/html/backend/src/schema/consent-record/schema.ts.html +211 -0
  108. package/coverage/html/backend/src/schema/consent-record/table.ts.html +457 -0
  109. package/coverage/html/backend/src/schema/create-registry.ts.html +148 -0
  110. package/coverage/html/backend/src/schema/definition.ts.html +685 -0
  111. package/coverage/html/backend/src/schema/domain/index.html +146 -0
  112. package/coverage/html/backend/src/schema/domain/registry.ts.html +973 -0
  113. package/coverage/html/backend/src/schema/domain/schema.ts.html +214 -0
  114. package/coverage/html/backend/src/schema/domain/table.ts.html +496 -0
  115. package/coverage/html/backend/src/schema/index.html +146 -0
  116. package/coverage/html/backend/src/schema/schemas.ts.html +166 -0
  117. package/coverage/html/backend/src/schema/subject/index.html +146 -0
  118. package/coverage/html/backend/src/schema/subject/registry.ts.html +973 -0
  119. package/coverage/html/backend/src/schema/subject/schema.ts.html +208 -0
  120. package/coverage/html/backend/src/schema/subject/table.ts.html +499 -0
  121. package/coverage/html/backend/src/server.ts.html +475 -0
  122. package/coverage/html/backend/src/testing/contract-testing.ts.html +1348 -0
  123. package/coverage/html/backend/src/testing/index.html +116 -0
  124. package/coverage/html/base.css +224 -0
  125. package/coverage/html/block-navigation.js +87 -0
  126. package/coverage/html/favicon.png +0 -0
  127. package/coverage/html/index.html +626 -0
  128. package/coverage/html/prettify.css +1 -0
  129. package/coverage/html/prettify.js +2 -0
  130. package/coverage/html/sort-arrow-sprite.png +0 -0
  131. package/coverage/html/sorter.js +196 -0
  132. package/dist/contracts/consent/index.d.ts +401 -0
  133. package/dist/contracts/consent/index.d.ts.map +1 -0
  134. package/dist/contracts/consent/index.test.d.ts +2 -0
  135. package/dist/contracts/consent/index.test.d.ts.map +1 -0
  136. package/dist/contracts/consent/post.contract.d.ts +212 -0
  137. package/dist/contracts/consent/post.contract.d.ts.map +1 -0
  138. package/dist/contracts/consent/post.contract.test.d.ts +2 -0
  139. package/dist/contracts/consent/post.contract.test.d.ts.map +1 -0
  140. package/dist/contracts/consent/show-banner.contract.d.ts +45 -0
  141. package/dist/contracts/consent/show-banner.contract.d.ts.map +1 -0
  142. package/dist/contracts/consent/show-banner.contract.test.d.ts +2 -0
  143. package/dist/contracts/consent/show-banner.contract.test.d.ts.map +1 -0
  144. package/dist/contracts/consent/verify.contract.d.ts +147 -0
  145. package/dist/contracts/consent/verify.contract.d.ts.map +1 -0
  146. package/dist/contracts/consent/verify.contract.test.d.ts +2 -0
  147. package/dist/contracts/consent/verify.contract.test.d.ts.map +1 -0
  148. package/dist/contracts/index.d.ts +963 -0
  149. package/dist/contracts/index.d.ts.map +1 -0
  150. package/dist/contracts/meta/index.d.ts +78 -0
  151. package/dist/contracts/meta/index.d.ts.map +1 -0
  152. package/dist/contracts/meta/index.test.d.ts +2 -0
  153. package/dist/contracts/meta/index.test.d.ts.map +1 -0
  154. package/dist/contracts/meta/status.contract.d.ts +77 -0
  155. package/dist/contracts/meta/status.contract.d.ts.map +1 -0
  156. package/dist/contracts/meta/status.contract.test.d.ts +2 -0
  157. package/dist/contracts/meta/status.contract.test.d.ts.map +1 -0
  158. package/dist/contracts/shared/jurisdiction.schema.d.ts +24 -0
  159. package/dist/contracts/shared/jurisdiction.schema.d.ts.map +1 -0
  160. package/dist/core.cjs +3584 -0
  161. package/dist/core.d.ts +533 -76
  162. package/dist/core.d.ts.map +1 -1
  163. package/dist/{index.js → core.js} +1163 -1286
  164. package/dist/handlers/consent/index.d.ts +401 -0
  165. package/dist/handlers/consent/index.d.ts.map +1 -0
  166. package/dist/handlers/consent/post.handler.d.ts +234 -0
  167. package/dist/handlers/consent/post.handler.d.ts.map +1 -0
  168. package/dist/handlers/consent/show-banner.handler.d.ts +57 -0
  169. package/dist/handlers/consent/show-banner.handler.d.ts.map +1 -0
  170. package/dist/handlers/consent/show-banner.handler.test.d.ts +2 -0
  171. package/dist/handlers/consent/show-banner.handler.test.d.ts.map +1 -0
  172. package/dist/handlers/consent/verify.handler.d.ts +169 -0
  173. package/dist/handlers/consent/verify.handler.d.ts.map +1 -0
  174. package/dist/handlers/meta/index.d.ts +78 -0
  175. package/dist/handlers/meta/index.d.ts.map +1 -0
  176. package/dist/handlers/meta/status.handler.d.ts +76 -0
  177. package/dist/handlers/meta/status.handler.d.ts.map +1 -0
  178. package/dist/init.d.ts.map +1 -1
  179. package/dist/pkgs/api-router/hooks/processor.d.ts.map +1 -1
  180. package/dist/pkgs/api-router/types/router-props.d.ts +1 -1
  181. package/dist/pkgs/api-router/types/router-props.d.ts.map +1 -1
  182. package/dist/pkgs/api-router/utils/cors.d.ts +1 -1
  183. package/dist/pkgs/api-router/utils/cors.d.ts.map +1 -1
  184. package/dist/pkgs/data-model/fields/field-types.d.ts +1 -1
  185. package/dist/pkgs/data-model/fields/zod-fields.d.ts +32 -32
  186. package/dist/pkgs/data-model/index.cjs +1433 -1799
  187. package/dist/pkgs/data-model/index.js +20 -385
  188. package/dist/pkgs/data-model/schema/index.cjs +1402 -1768
  189. package/dist/pkgs/data-model/schema/index.js +20 -385
  190. package/dist/pkgs/db-adapters/adapter-factory.d.ts +2 -2
  191. package/dist/pkgs/db-adapters/adapter-factory.d.ts.map +1 -1
  192. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.d.ts +4 -4
  193. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.cjs +19 -151
  194. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.js +19 -151
  195. package/dist/pkgs/db-adapters/adapters/kysely-adapter/dialect.d.ts +1 -1
  196. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.cjs +17 -149
  197. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.js +17 -149
  198. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts +2 -2
  199. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts.map +1 -1
  200. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.cjs +17 -149
  201. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.js +17 -149
  202. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.cjs +19 -151
  203. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.js +19 -151
  204. package/dist/pkgs/db-adapters/index.cjs +31 -153
  205. package/dist/pkgs/db-adapters/index.js +31 -153
  206. package/dist/pkgs/migrations/get-schema/get-schema.d.ts +2 -2
  207. package/dist/pkgs/migrations/get-schema/index.d.ts +1 -1
  208. package/dist/pkgs/migrations/index.cjs +30 -153
  209. package/dist/pkgs/migrations/index.js +30 -153
  210. package/dist/pkgs/migrations/schema-comparison.d.ts.map +1 -1
  211. package/dist/pkgs/results/core/error-class.d.ts +23 -21
  212. package/dist/pkgs/results/core/error-class.d.ts.map +1 -1
  213. package/dist/pkgs/results/index.cjs +17 -150
  214. package/dist/pkgs/results/index.d.ts +0 -3
  215. package/dist/pkgs/results/index.d.ts.map +1 -1
  216. package/dist/pkgs/results/index.js +17 -138
  217. package/dist/pkgs/results/orpc-error-handler.d.ts +65 -0
  218. package/dist/pkgs/results/orpc-error-handler.d.ts.map +1 -0
  219. package/dist/pkgs/results/types.d.ts +7 -7
  220. package/dist/pkgs/results/types.d.ts.map +1 -1
  221. package/dist/pkgs/types/context.d.ts +15 -4
  222. package/dist/pkgs/types/context.d.ts.map +1 -1
  223. package/dist/pkgs/types/endpoints.d.ts +3 -4
  224. package/dist/pkgs/types/endpoints.d.ts.map +1 -1
  225. package/dist/pkgs/types/options.d.ts +2 -3
  226. package/dist/pkgs/types/options.d.ts.map +1 -1
  227. package/dist/pkgs/types/plugins.d.ts +2 -3
  228. package/dist/pkgs/types/plugins.d.ts.map +1 -1
  229. package/dist/pkgs/utils/index.d.ts +1 -0
  230. package/dist/pkgs/utils/index.d.ts.map +1 -1
  231. package/dist/pkgs/utils/logger.d.ts +16 -0
  232. package/dist/pkgs/utils/logger.d.ts.map +1 -0
  233. package/dist/router.cjs +1213 -0
  234. package/dist/router.d.ts +480 -0
  235. package/dist/router.d.ts.map +1 -0
  236. package/dist/router.js +1169 -0
  237. package/dist/schema/audit-log/table.d.ts +1 -1
  238. package/dist/schema/consent/table.d.ts +1 -1
  239. package/dist/schema/consent-policy/registry.d.ts +12 -12
  240. package/dist/schema/consent-policy/schema.d.ts +6 -6
  241. package/dist/schema/consent-policy/table.d.ts +7 -7
  242. package/dist/schema/consent-purpose/registry.d.ts +6 -6
  243. package/dist/schema/consent-purpose/schema.d.ts +6 -6
  244. package/dist/schema/consent-purpose/table.d.ts +7 -7
  245. package/dist/schema/consent-record/table.d.ts +1 -1
  246. package/dist/schema/create-registry.d.ts +32 -32
  247. package/dist/schema/definition.d.ts +19 -19
  248. package/dist/schema/domain/registry.d.ts +10 -10
  249. package/dist/schema/domain/schema.d.ts +5 -5
  250. package/dist/schema/domain/table.d.ts +6 -6
  251. package/dist/schema/index.cjs +1409 -1775
  252. package/dist/schema/index.js +20 -385
  253. package/dist/schema/schemas.d.ts +19 -19
  254. package/dist/schema/subject/registry.d.ts +4 -4
  255. package/dist/schema/subject/schema.d.ts +2 -2
  256. package/dist/schema/subject/table.d.ts +3 -3
  257. package/dist/server.d.ts +2 -0
  258. package/dist/server.d.ts.map +1 -0
  259. package/dist/testing/contract-testing.d.ts +37 -0
  260. package/dist/testing/contract-testing.d.ts.map +1 -0
  261. package/dist/types/context.d.ts +1 -1
  262. package/dist/types/index.d.ts +2 -2
  263. package/dist/types/options.d.ts +33 -2
  264. package/dist/types/options.d.ts.map +1 -1
  265. package/dist/types/plugins.d.ts +3 -4
  266. package/dist/types/plugins.d.ts.map +1 -1
  267. package/package.json +22 -30
  268. package/rslib.config.ts +2 -5
  269. package/src/contracts/consent/index.test.ts +5 -0
  270. package/src/contracts/consent/index.ts +9 -0
  271. package/src/contracts/consent/post.contract.test.ts +526 -0
  272. package/src/contracts/consent/post.contract.ts +160 -0
  273. package/src/contracts/consent/show-banner.contract.test.ts +214 -0
  274. package/src/contracts/consent/show-banner.contract.ts +45 -0
  275. package/src/contracts/consent/verify.contract.test.ts +185 -0
  276. package/src/contracts/consent/verify.contract.ts +126 -0
  277. package/src/contracts/index.ts +18 -0
  278. package/src/contracts/meta/index.test.ts +5 -0
  279. package/src/contracts/meta/index.ts +5 -0
  280. package/src/contracts/meta/status.contract.test.ts +338 -0
  281. package/src/contracts/meta/status.contract.ts +37 -0
  282. package/src/contracts/shared/jurisdiction.schema.ts +30 -0
  283. package/src/core.ts +451 -159
  284. package/src/handlers/consent/index.ts +9 -0
  285. package/src/handlers/consent/post.handler.ts +273 -0
  286. package/src/handlers/consent/show-banner.handler.test.ts +148 -0
  287. package/src/handlers/consent/show-banner.handler.ts +150 -0
  288. package/src/handlers/consent/verify.handler.ts +305 -0
  289. package/src/handlers/meta/index.ts +5 -0
  290. package/src/handlers/meta/status.handler.ts +47 -0
  291. package/src/init.ts +8 -5
  292. package/src/pkgs/api-router/hooks/__tests__/processor.test.ts +6 -0
  293. package/src/pkgs/api-router/hooks/processor.ts +2 -0
  294. package/src/pkgs/api-router/types/router-props.ts +1 -1
  295. package/src/pkgs/api-router/utils/cors.ts +1 -1
  296. package/src/pkgs/data-model/fields/field-types.ts +1 -1
  297. package/src/pkgs/data-model/fields/id-generator.ts +1 -1
  298. package/src/pkgs/db-adapters/README.md +3 -3
  299. package/src/pkgs/db-adapters/adapter-factory.ts +8 -4
  300. package/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts +13 -13
  301. package/src/pkgs/db-adapters/adapters/kysely-adapter/dialect.ts +1 -1
  302. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/postgres.test.ts +1 -1
  303. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/sqlite.test.ts +1 -1
  304. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts +2 -2
  305. package/src/pkgs/migrations/get-migration.ts +3 -3
  306. package/src/pkgs/migrations/get-schema/get-schema.ts +2 -2
  307. package/src/pkgs/migrations/get-schema/index.ts +1 -1
  308. package/src/pkgs/migrations/migration-builders.ts +2 -2
  309. package/src/pkgs/migrations/migration-execution.ts +2 -2
  310. package/src/pkgs/migrations/schema-comparison.ts +5 -4
  311. package/src/pkgs/results/__tests__/error-class.test.ts +8 -7
  312. package/src/pkgs/results/core/error-class.ts +31 -43
  313. package/src/pkgs/results/index.ts +0 -10
  314. package/src/pkgs/results/orpc-error-handler.ts +137 -0
  315. package/src/pkgs/results/types.ts +8 -7
  316. package/src/pkgs/types/context.ts +18 -4
  317. package/src/pkgs/types/endpoints.ts +3 -5
  318. package/src/pkgs/types/options.ts +2 -3
  319. package/src/pkgs/types/plugins.ts +2 -3
  320. package/src/pkgs/utils/index.ts +1 -0
  321. package/src/pkgs/utils/logger.ts +38 -0
  322. package/src/router.ts +8 -0
  323. package/src/schema/audit-log/table.ts +1 -1
  324. package/src/schema/consent/table.ts +1 -1
  325. package/src/schema/consent-policy/table.ts +1 -1
  326. package/src/schema/consent-purpose/table.ts +1 -1
  327. package/src/schema/consent-record/table.ts +1 -1
  328. package/src/schema/definition.ts +2 -2
  329. package/src/schema/domain/table.ts +1 -1
  330. package/src/schema/subject/table.ts +1 -1
  331. package/src/server.ts +130 -0
  332. package/src/testing/contract-testing.ts +437 -0
  333. package/src/types/context.ts +1 -1
  334. package/src/types/index.ts +2 -2
  335. package/src/types/options.ts +38 -2
  336. package/src/types/plugins.ts +3 -4
  337. package/dist/index.cjs +0 -3701
  338. package/dist/index.d.ts +0 -11
  339. package/dist/index.d.ts.map +0 -1
  340. package/dist/init.test.d.ts +0 -2
  341. package/dist/init.test.d.ts.map +0 -1
  342. package/dist/integrations/cloudflare.cjs +0 -312
  343. package/dist/integrations/cloudflare.d.ts +0 -32
  344. package/dist/integrations/cloudflare.d.ts.map +0 -1
  345. package/dist/integrations/cloudflare.js +0 -278
  346. package/dist/integrations/next.cjs +0 -276
  347. package/dist/integrations/next.d.ts +0 -68
  348. package/dist/integrations/next.d.ts.map +0 -1
  349. package/dist/integrations/next.js +0 -239
  350. package/dist/integrations/node.cjs +0 -257
  351. package/dist/integrations/node.d.ts +0 -29
  352. package/dist/integrations/node.d.ts.map +0 -1
  353. package/dist/integrations/node.js +0 -223
  354. package/dist/pkgs/api-router/index.d.ts +0 -9
  355. package/dist/pkgs/api-router/index.d.ts.map +0 -1
  356. package/dist/pkgs/api-router/utils/define-route.d.ts +0 -87
  357. package/dist/pkgs/api-router/utils/define-route.d.ts.map +0 -1
  358. package/dist/pkgs/logger/__tests__/console-formatter.test.d.ts +0 -2
  359. package/dist/pkgs/logger/__tests__/console-formatter.test.d.ts.map +0 -1
  360. package/dist/pkgs/logger/__tests__/integration.test.d.ts +0 -2
  361. package/dist/pkgs/logger/__tests__/integration.test.d.ts.map +0 -1
  362. package/dist/pkgs/logger/__tests__/log-levels.test.d.ts +0 -2
  363. package/dist/pkgs/logger/__tests__/log-levels.test.d.ts.map +0 -1
  364. package/dist/pkgs/logger/__tests__/logger-factory.test.d.ts +0 -2
  365. package/dist/pkgs/logger/__tests__/logger-factory.test.d.ts.map +0 -1
  366. package/dist/pkgs/logger/__tests__/result-logging.test.d.ts +0 -2
  367. package/dist/pkgs/logger/__tests__/result-logging.test.d.ts.map +0 -1
  368. package/dist/pkgs/logger/__tests__/types.test.d.ts +0 -2
  369. package/dist/pkgs/logger/__tests__/types.test.d.ts.map +0 -1
  370. package/dist/pkgs/logger/console-formatter.d.ts +0 -56
  371. package/dist/pkgs/logger/console-formatter.d.ts.map +0 -1
  372. package/dist/pkgs/logger/index.cjs +0 -240
  373. package/dist/pkgs/logger/index.d.ts +0 -35
  374. package/dist/pkgs/logger/index.d.ts.map +0 -1
  375. package/dist/pkgs/logger/index.js +0 -185
  376. package/dist/pkgs/logger/log-levels.d.ts +0 -29
  377. package/dist/pkgs/logger/log-levels.d.ts.map +0 -1
  378. package/dist/pkgs/logger/logger-factory.d.ts +0 -42
  379. package/dist/pkgs/logger/logger-factory.d.ts.map +0 -1
  380. package/dist/pkgs/logger/result-logging.d.ts +0 -71
  381. package/dist/pkgs/logger/result-logging.d.ts.map +0 -1
  382. package/dist/pkgs/logger/telemetry.d.ts +0 -14
  383. package/dist/pkgs/logger/telemetry.d.ts.map +0 -1
  384. package/dist/pkgs/logger/types.d.ts +0 -121
  385. package/dist/pkgs/logger/types.d.ts.map +0 -1
  386. package/dist/pkgs/results/__tests__/retrieval-pipeline.test.d.ts +0 -2
  387. package/dist/pkgs/results/__tests__/retrieval-pipeline.test.d.ts.map +0 -1
  388. package/dist/pkgs/results/__tests__/validation-pipeline.test.d.ts +0 -2
  389. package/dist/pkgs/results/__tests__/validation-pipeline.test.d.ts.map +0 -1
  390. package/dist/pkgs/results/h3-integration.d.ts +0 -52
  391. package/dist/pkgs/results/h3-integration.d.ts.map +0 -1
  392. package/dist/pkgs/results/pipeline/retrieval-pipeline.d.ts +0 -101
  393. package/dist/pkgs/results/pipeline/retrieval-pipeline.d.ts.map +0 -1
  394. package/dist/pkgs/results/pipeline/validation-pipeline.d.ts +0 -89
  395. package/dist/pkgs/results/pipeline/validation-pipeline.d.ts.map +0 -1
  396. package/dist/response-types.d.ts +0 -19
  397. package/dist/response-types.d.ts.map +0 -1
  398. package/dist/routes/__test__/index.test.d.ts +0 -17
  399. package/dist/routes/__test__/index.test.d.ts.map +0 -1
  400. package/dist/routes/__test__/set-consent.test.d.ts +0 -2
  401. package/dist/routes/__test__/set-consent.test.d.ts.map +0 -1
  402. package/dist/routes/__test__/show-consent-banner.test.d.ts +0 -2
  403. package/dist/routes/__test__/show-consent-banner.test.d.ts.map +0 -1
  404. package/dist/routes/__test__/status.test.d.ts +0 -2
  405. package/dist/routes/__test__/status.test.d.ts.map +0 -1
  406. package/dist/routes/__test__/verify-consent.test.d.ts +0 -2
  407. package/dist/routes/__test__/verify-consent.test.d.ts.map +0 -1
  408. package/dist/routes/index.d.ts +0 -3
  409. package/dist/routes/index.d.ts.map +0 -1
  410. package/dist/routes/set-consent.d.ts +0 -89
  411. package/dist/routes/set-consent.d.ts.map +0 -1
  412. package/dist/routes/show-consent-banner.d.ts +0 -15
  413. package/dist/routes/show-consent-banner.d.ts.map +0 -1
  414. package/dist/routes/status.d.ts +0 -44
  415. package/dist/routes/status.d.ts.map +0 -1
  416. package/dist/routes/types.d.ts +0 -7
  417. package/dist/routes/types.d.ts.map +0 -1
  418. package/dist/routes/verify-consent.d.ts +0 -38
  419. package/dist/routes/verify-consent.d.ts.map +0 -1
  420. package/src/docs/ADVANCED_JSON_HANDLING.md +0 -99
  421. package/src/docs/neverthrow.md +0 -171
  422. package/src/index.ts +0 -34
  423. package/src/init.test.ts +0 -219
  424. package/src/integrations/cloudflare.ts +0 -269
  425. package/src/integrations/next.ts +0 -204
  426. package/src/integrations/node.ts +0 -141
  427. package/src/pkgs/api-router/index.ts +0 -148
  428. package/src/pkgs/api-router/types/h3.d.ts +0 -42
  429. package/src/pkgs/api-router/utils/define-route.ts +0 -410
  430. package/src/pkgs/logger/README.md +0 -213
  431. package/src/pkgs/logger/__tests__/console-formatter.test.ts +0 -67
  432. package/src/pkgs/logger/__tests__/integration.test.ts +0 -184
  433. package/src/pkgs/logger/__tests__/log-levels.test.ts +0 -77
  434. package/src/pkgs/logger/__tests__/logger-factory.test.ts +0 -156
  435. package/src/pkgs/logger/__tests__/result-logging.test.ts +0 -209
  436. package/src/pkgs/logger/__tests__/types.test.ts +0 -94
  437. package/src/pkgs/logger/console-formatter.ts +0 -75
  438. package/src/pkgs/logger/doc.md +0 -569
  439. package/src/pkgs/logger/index.ts +0 -59
  440. package/src/pkgs/logger/log-levels.ts +0 -46
  441. package/src/pkgs/logger/logger-factory.ts +0 -121
  442. package/src/pkgs/logger/result-logging.ts +0 -134
  443. package/src/pkgs/logger/telemetry.ts +0 -96
  444. package/src/pkgs/logger/types.ts +0 -138
  445. package/src/pkgs/results/__tests__/retrieval-pipeline.test.ts +0 -157
  446. package/src/pkgs/results/__tests__/validation-pipeline.test.ts +0 -151
  447. package/src/pkgs/results/h3-integration.ts +0 -142
  448. package/src/pkgs/results/pipeline/retrieval-pipeline.ts +0 -188
  449. package/src/pkgs/results/pipeline/validation-pipeline.ts +0 -164
  450. package/src/plugins/.keep +0 -0
  451. package/src/response-types.ts +0 -29
  452. package/src/routes/__test__/index.test.ts +0 -112
  453. package/src/routes/__test__/set-consent.test.ts +0 -242
  454. package/src/routes/__test__/show-consent-banner.test.ts +0 -98
  455. package/src/routes/__test__/status.test.ts +0 -64
  456. package/src/routes/__test__/verify-consent.test.ts +0 -266
  457. package/src/routes/index.ts +0 -12
  458. package/src/routes/set-consent.ts +0 -249
  459. package/src/routes/show-consent-banner.ts +0 -131
  460. package/src/routes/status.ts +0 -61
  461. package/src/routes/types.ts +0 -7
  462. package/src/routes/verify-consent.ts +0 -206
@@ -0,0 +1,526 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { z } from 'zod';
3
+
4
+ import { PolicyTypeSchema } from '~/schema';
5
+ import { createContractTests } from '~/testing/contract-testing';
6
+
7
+ import { postConsentContract } from './post.contract';
8
+
9
+ // Create base tests for the contract using the utility
10
+ const tester = createContractTests('Post Consent', postConsentContract);
11
+
12
+ // Keep the detailed custom tests to maintain existing coverage
13
+ describe('Post Consent Contract Custom Tests', () => {
14
+ // Helper to access schemas consistently throughout tests
15
+ const schemas = {
16
+ input: postConsentContract['~orpc'].inputSchema,
17
+ output: postConsentContract['~orpc'].outputSchema,
18
+ };
19
+
20
+ // Helper functions for common test patterns
21
+ const validateInput = (input: unknown) => {
22
+ return schemas.input?.safeParse(input);
23
+ };
24
+
25
+ const validateOutput = (output: unknown) => {
26
+ return schemas.output?.safeParse(output);
27
+ };
28
+
29
+ describe('Schema Structure', () => {
30
+ it('input schema is a discriminated union based on type', () => {
31
+ // Using explicit type cast to avoid linter warnings
32
+ const schema = schemas.input as z.ZodDiscriminatedUnion<
33
+ string,
34
+ z.ZodObject<z.ZodRawShape>[]
35
+ >;
36
+ expect(schema._def.typeName).toBe('ZodDiscriminatedUnion');
37
+ expect(schema._def.discriminator).toBe('type');
38
+ });
39
+
40
+ it('supports all defined policy types', () => {
41
+ const policyTypes = PolicyTypeSchema.options;
42
+
43
+ for (const type of policyTypes) {
44
+ const input = {
45
+ type,
46
+ domain: 'example.com',
47
+ ...(type === 'cookie_banner' ? { preferences: { test: true } } : {}),
48
+ };
49
+
50
+ const result = validateInput(input);
51
+ expect(result?.success).toBe(true);
52
+ }
53
+ });
54
+ });
55
+
56
+ describe('Input Validation', () => {
57
+ describe('cookie_banner type', () => {
58
+ it('accepts valid input with preferences', () => {
59
+ const validInput = {
60
+ type: 'cookie_banner',
61
+ domain: 'example.com',
62
+ preferences: { analytics: true, marketing: false },
63
+ } as const;
64
+
65
+ const result = validateInput(validInput);
66
+ expect(result?.success).toBe(true);
67
+ });
68
+
69
+ it('rejects input without required preferences', () => {
70
+ const invalidInput = {
71
+ type: 'cookie_banner',
72
+ domain: 'example.com',
73
+ } as const;
74
+
75
+ const result = validateInput(invalidInput);
76
+ if (!result) {
77
+ throw new Error('Result is undefined');
78
+ }
79
+
80
+ expect(result.success).toBe(false);
81
+ if (!result.success) {
82
+ // Use optional chaining to safely access potentially undefined properties
83
+ expect(result.error.issues?.[0]?.path).toContain('preferences');
84
+ }
85
+ });
86
+
87
+ it('verifies boolean values in preferences', () => {
88
+ const invalidPreferences = {
89
+ type: 'cookie_banner',
90
+ domain: 'example.com',
91
+ preferences: { analytics: 'yes' }, // Should be boolean
92
+ };
93
+
94
+ const result = validateInput(invalidPreferences);
95
+ if (!result) {
96
+ throw new Error('Result is undefined');
97
+ }
98
+
99
+ expect(result.success).toBe(false);
100
+ if (!result.success) {
101
+ expect(result.error.issues?.[0]?.path).toContain('preferences');
102
+ }
103
+ });
104
+ });
105
+
106
+ describe('policy-based types', () => {
107
+ it('validates privacy_policy input', () => {
108
+ const validInput = {
109
+ type: 'privacy_policy',
110
+ domain: 'example.com',
111
+ policyId: 'policy-123',
112
+ } as const;
113
+
114
+ const result = validateInput(validInput);
115
+ expect(result?.success).toBe(true);
116
+ });
117
+
118
+ it('validates dpa input', () => {
119
+ const validInput = {
120
+ type: 'dpa',
121
+ domain: 'example.com',
122
+ policyId: 'dpa-123',
123
+ };
124
+
125
+ const result = validateInput(validInput);
126
+ expect(result?.success).toBe(true);
127
+ });
128
+
129
+ it('validates terms_and_conditions input', () => {
130
+ const validInput = {
131
+ type: 'terms_and_conditions',
132
+ domain: 'example.com',
133
+ policyId: 'terms-123',
134
+ };
135
+
136
+ const result = validateInput(validInput);
137
+ expect(result?.success).toBe(true);
138
+ });
139
+
140
+ it('accepts optional preferences for policy-based consents', () => {
141
+ const validInput = {
142
+ type: 'privacy_policy',
143
+ domain: 'example.com',
144
+ policyId: 'policy-123',
145
+ preferences: { acceptAll: true, marketing: false },
146
+ };
147
+
148
+ const result = validateInput(validInput);
149
+ expect(result?.success).toBe(true);
150
+ });
151
+ });
152
+
153
+ describe('other consent types', () => {
154
+ it('validates marketing_communications input', () => {
155
+ const validInput = {
156
+ type: 'marketing_communications',
157
+ domain: 'example.com',
158
+ subjectId: 'user-123',
159
+ } as const;
160
+
161
+ const result = validateInput(validInput);
162
+ if (!result) {
163
+ throw new Error('Result is undefined');
164
+ }
165
+
166
+ expect(result.success).toBe(true);
167
+ });
168
+
169
+ it('validates age_verification input', () => {
170
+ const validInput = {
171
+ type: 'age_verification',
172
+ domain: 'example.com',
173
+ };
174
+
175
+ const result = validateInput(validInput);
176
+ expect(result?.success).toBe(true);
177
+ });
178
+
179
+ it('validates other type input', () => {
180
+ const validInput = {
181
+ type: 'other',
182
+ domain: 'example.com',
183
+ metadata: { customField: 'value' },
184
+ };
185
+
186
+ const result = validateInput(validInput);
187
+ expect(result?.success).toBe(true);
188
+ });
189
+ });
190
+
191
+ describe('common requirements', () => {
192
+ it('rejects input with invalid type', () => {
193
+ const invalidInput = {
194
+ // Type cast to bypass TS errors for testing
195
+ type: 'invalid_type' as unknown as z.infer<typeof PolicyTypeSchema>,
196
+ domain: 'example.com',
197
+ };
198
+
199
+ const result = validateInput(invalidInput);
200
+
201
+ if (!result) {
202
+ throw new Error('Result is undefined');
203
+ }
204
+
205
+ expect(result.success).toBe(false);
206
+ if (!result.success) {
207
+ expect(result.error.issues?.[0]?.path).toContain('type');
208
+ }
209
+ });
210
+
211
+ it('requires domain field', () => {
212
+ const invalidInput = {
213
+ type: 'marketing_communications' as z.infer<typeof PolicyTypeSchema>,
214
+ };
215
+
216
+ const result = validateInput(invalidInput);
217
+ if (!result) {
218
+ throw new Error('Result is undefined');
219
+ }
220
+
221
+ expect(result.success).toBe(false);
222
+ if (!result.success) {
223
+ expect(result.error.issues?.[0]?.path).toContain('domain');
224
+ }
225
+ });
226
+
227
+ it('accepts additional metadata', () => {
228
+ const validInput = {
229
+ type: 'marketing_communications',
230
+ domain: 'example.com',
231
+ metadata: {
232
+ source: 'web',
233
+ campaign: 'summer2023',
234
+ customData: { nested: true },
235
+ },
236
+ };
237
+
238
+ const result = validateInput(validInput);
239
+ expect(result?.success).toBe(true);
240
+ });
241
+
242
+ it('accepts optional subjectId', () => {
243
+ const validInput = {
244
+ type: 'privacy_policy',
245
+ domain: 'example.com',
246
+ subjectId: 'user-abc-123',
247
+ };
248
+
249
+ const result = validateInput(validInput);
250
+ expect(result?.success).toBe(true);
251
+ });
252
+
253
+ it('accepts optional externalSubjectId', () => {
254
+ const validInput = {
255
+ type: 'privacy_policy',
256
+ domain: 'example.com',
257
+ externalSubjectId: 'external-user-123',
258
+ };
259
+
260
+ const result = validateInput(validInput);
261
+ expect(result?.success).toBe(true);
262
+ });
263
+ });
264
+ });
265
+
266
+ describe('Output Validation', () => {
267
+ it('validates complete output object', () => {
268
+ const validOutput = {
269
+ id: '123',
270
+ domainId: '456',
271
+ domain: 'example.com',
272
+ type: 'marketing_communications',
273
+ status: 'granted',
274
+ recordId: '789',
275
+ givenAt: new Date(),
276
+ metadata: { source: 'web' },
277
+ } as const;
278
+
279
+ const result = validateOutput(validOutput);
280
+ if (!result) {
281
+ throw new Error('Result is undefined');
282
+ }
283
+
284
+ expect(result.success).toBe(true);
285
+ });
286
+
287
+ it('rejects output without required fields', () => {
288
+ const invalidOutput = {
289
+ id: '123',
290
+ domain: 'example.com',
291
+ type: 'marketing_communications',
292
+ // Missing required fields: domainId, status, recordId, givenAt
293
+ } as const;
294
+
295
+ const result = validateOutput(invalidOutput);
296
+ if (!result) {
297
+ throw new Error('Result is undefined');
298
+ }
299
+
300
+ expect(result.success).toBe(false);
301
+ });
302
+
303
+ it('validates output with all possible status values', () => {
304
+ const statusValues = ['granted', 'denied', 'pending', 'withdrawn'];
305
+
306
+ for (const status of statusValues) {
307
+ const output = {
308
+ id: '123',
309
+ domainId: '456',
310
+ domain: 'example.com',
311
+ type: 'marketing_communications',
312
+ status,
313
+ recordId: '789',
314
+ givenAt: new Date(),
315
+ };
316
+
317
+ const result = validateOutput(output);
318
+ expect(result?.success).toBe(true);
319
+ }
320
+ });
321
+
322
+ it('validates output with different policy types', () => {
323
+ const policyTypes = PolicyTypeSchema.options;
324
+
325
+ for (const type of policyTypes) {
326
+ const output = {
327
+ id: '123',
328
+ domainId: '456',
329
+ domain: 'example.com',
330
+ type,
331
+ status: 'granted',
332
+ recordId: '789',
333
+ givenAt: new Date(),
334
+ };
335
+
336
+ const result = validateOutput(output);
337
+ expect(result?.success).toBe(true);
338
+ }
339
+ });
340
+
341
+ describe('givenAt field', () => {
342
+ it('rejects string values', () => {
343
+ const invalidOutput = {
344
+ id: '123',
345
+ domainId: '456',
346
+ domain: 'example.com',
347
+ type: 'marketing_communications',
348
+ status: 'granted',
349
+ recordId: '789',
350
+ givenAt: 'not-a-date', // This should now fail with z.date()
351
+ metadata: {},
352
+ } as const;
353
+
354
+ const result = validateOutput(invalidOutput);
355
+ if (!result) {
356
+ throw new Error('Result is undefined');
357
+ }
358
+
359
+ expect(result.success).toBe(false);
360
+ });
361
+
362
+ it('accepts Date objects', () => {
363
+ const validOutput = {
364
+ id: '123',
365
+ domainId: '456',
366
+ domain: 'example.com',
367
+ type: 'marketing_communications',
368
+ status: 'granted',
369
+ recordId: '789',
370
+ givenAt: new Date(),
371
+ metadata: {},
372
+ };
373
+
374
+ const result = validateOutput(validOutput);
375
+ expect(result?.success).toBe(true);
376
+ });
377
+
378
+ it('rejects non-date values', () => {
379
+ const invalidOutput = {
380
+ id: '123',
381
+ domainId: '456',
382
+ domain: 'example.com',
383
+ type: 'marketing_communications',
384
+ status: 'granted',
385
+ recordId: '789',
386
+ givenAt: 123, // Number instead of Date
387
+ metadata: {},
388
+ };
389
+
390
+ const result = validateOutput(invalidOutput);
391
+ expect(result?.success).toBe(false);
392
+ });
393
+
394
+ it('accepts ISO date strings', () => {
395
+ const validOutput = {
396
+ id: '123',
397
+ domainId: '456',
398
+ domain: 'example.com',
399
+ type: 'marketing_communications',
400
+ status: 'granted',
401
+ recordId: '789',
402
+ givenAt: new Date(),
403
+ metadata: {},
404
+ };
405
+
406
+ const result = validateOutput(validOutput);
407
+ expect(result?.success).toBe(true);
408
+ });
409
+
410
+ it('rejects non-string values', () => {
411
+ // Create an object with a number for givenAt (should fail validation)
412
+ const invalidOutput = {
413
+ id: '123',
414
+ domainId: '456',
415
+ domain: 'example.com',
416
+ type: 'marketing_communications',
417
+ status: 'granted',
418
+ recordId: '789',
419
+ givenAt: 123, // Number instead of string (intentionally invalid)
420
+ metadata: {},
421
+ };
422
+
423
+ // We need to cast here because TypeScript wouldn't allow this invalid type normally
424
+ const result = validateOutput(invalidOutput);
425
+ if (!result) {
426
+ throw new Error('Result is undefined');
427
+ }
428
+
429
+ expect(result.success).toBe(false);
430
+ if (!result.success) {
431
+ expect(result.error.issues?.[0]?.path).toContain('givenAt');
432
+ }
433
+ });
434
+ });
435
+
436
+ describe('Optional fields validation', () => {
437
+ it('accepts output without optional fields', () => {
438
+ const validOutput = {
439
+ id: '123',
440
+ domainId: '456',
441
+ domain: 'example.com',
442
+ type: 'marketing_communications',
443
+ status: 'granted',
444
+ recordId: '789',
445
+ givenAt: new Date(),
446
+ // No metadata, subjectId or externalSubjectId
447
+ };
448
+
449
+ const result = validateOutput(validOutput);
450
+ expect(result?.success).toBe(true);
451
+ });
452
+
453
+ it('accepts output with optional subjectId', () => {
454
+ const validOutput = {
455
+ id: '123',
456
+ domainId: '456',
457
+ domain: 'example.com',
458
+ type: 'marketing_communications',
459
+ status: 'granted',
460
+ recordId: '789',
461
+ givenAt: new Date(),
462
+ subjectId: 'user-123',
463
+ };
464
+
465
+ const result = validateOutput(validOutput);
466
+ expect(result?.success).toBe(true);
467
+ });
468
+
469
+ it('accepts output with optional externalSubjectId', () => {
470
+ const validOutput = {
471
+ id: '123',
472
+ domainId: '456',
473
+ domain: 'example.com',
474
+ type: 'marketing_communications',
475
+ status: 'granted',
476
+ recordId: '789',
477
+ givenAt: new Date(),
478
+ externalSubjectId: 'external-user-123',
479
+ };
480
+
481
+ const result = validateOutput(validOutput);
482
+ expect(result?.success).toBe(true);
483
+ });
484
+
485
+ it('accepts output with complex metadata', () => {
486
+ const validOutput = {
487
+ id: '123',
488
+ domainId: '456',
489
+ domain: 'example.com',
490
+ type: 'marketing_communications',
491
+ status: 'granted',
492
+ recordId: '789',
493
+ givenAt: new Date(),
494
+ metadata: {
495
+ source: 'web',
496
+ platform: 'mobile',
497
+ browser: { name: 'Chrome', version: '115' },
498
+ consentMethod: 'explicit',
499
+ nestedData: {
500
+ level1: {
501
+ level2: {
502
+ level3: true,
503
+ },
504
+ },
505
+ },
506
+ },
507
+ };
508
+
509
+ const result = validateOutput(validOutput);
510
+ expect(result?.success).toBe(true);
511
+ });
512
+ });
513
+ });
514
+ });
515
+
516
+ // Add required fields testing using the utility
517
+ tester.testRequiredFields('input', ['domain', 'type']);
518
+ tester.testRequiredFields('output', [
519
+ 'id',
520
+ 'domainId',
521
+ 'domain',
522
+ 'type',
523
+ 'status',
524
+ 'recordId',
525
+ 'givenAt',
526
+ ]);
@@ -0,0 +1,160 @@
1
+ import { oc } from '@orpc/contract';
2
+ import { z } from 'zod';
3
+
4
+ import { PolicyTypeSchema } from '~/schema';
5
+
6
+ const baseConsentSchema = z.object({
7
+ subjectId: z.string().optional(),
8
+ externalSubjectId: z.string().optional(),
9
+ domain: z
10
+ .string()
11
+ .regex(
12
+ /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i,
13
+ 'invalid domain'
14
+ ),
15
+ type: PolicyTypeSchema,
16
+ metadata: z.record(z.unknown()).optional(),
17
+ });
18
+
19
+ // Cookie banner needs preferences
20
+ const cookieBannerSchema = baseConsentSchema.extend({
21
+ type: z.literal('cookie_banner'),
22
+ preferences: z.record(z.boolean()),
23
+ });
24
+
25
+ // Policy based consent just needs the policy ID
26
+ const policyBasedSchema = baseConsentSchema.extend({
27
+ type: z.enum(['privacy_policy', 'dpa', 'terms_and_conditions']),
28
+ policyId: z.string().optional(),
29
+ preferences: z.record(z.boolean()).optional(),
30
+ });
31
+
32
+ // Other consent types just need the base fields
33
+ const otherConsentSchema = baseConsentSchema.extend({
34
+ type: z.enum(['marketing_communications', 'age_verification', 'other']),
35
+ preferences: z.record(z.boolean()).optional(),
36
+ });
37
+
38
+ export const postConsentContract = oc
39
+ .route({
40
+ method: 'POST',
41
+ path: '/consent/set',
42
+ description: `Records a user's consent preferences and creates necessary consent records.
43
+ This endpoint handles various types of consent submissions:
44
+
45
+ 1. Cookie Banner Consent:
46
+ - Records granular cookie preferences
47
+ - Supports multiple consent purposes
48
+ - Creates audit trail for compliance
49
+
50
+ 2. Policy-Based Consent:
51
+ - Privacy Policy acceptance
52
+ - Data Processing Agreement (DPA) consent
53
+ - Terms and Conditions acceptance
54
+ - Links consent to specific policy versions
55
+
56
+ 3. Other Consent Types:
57
+ - Marketing communications preferences
58
+ - Age verification consent
59
+ - Custom consent types
60
+
61
+ The endpoint performs the following operations:
62
+ - Creates or retrieves subject records
63
+ - Validates domain and policy information
64
+ - Creates consent records with audit trails
65
+ - Records consent purposes and preferences
66
+ - Generates audit logs for compliance
67
+
68
+ Use this endpoint to record user consent and maintain a compliant consent management system.`,
69
+ tags: ['consent', 'cookie-banner'],
70
+ })
71
+ .errors({
72
+ // Input validation errors
73
+ INPUT_VALIDATION_FAILED: {
74
+ status: 422,
75
+ message: 'Invalid input parameters',
76
+ data: z.object({
77
+ formErrors: z.array(z.string()),
78
+ fieldErrors: z.record(z.string(), z.array(z.string())),
79
+ }),
80
+ },
81
+ // Subject errors
82
+ SUBJECT_CREATION_FAILED: {
83
+ status: 400,
84
+ message: 'Failed to create or find subject',
85
+ data: z.object({
86
+ subjectId: z.string().optional(),
87
+ externalSubjectId: z.string().optional(),
88
+ }),
89
+ },
90
+ // Domain errors
91
+ DOMAIN_CREATION_FAILED: {
92
+ status: 500,
93
+ message: 'Failed to create or find domain',
94
+ data: z.object({
95
+ domain: z.string(),
96
+ }),
97
+ },
98
+ // Policy errors
99
+ POLICY_NOT_FOUND: {
100
+ status: 404,
101
+ message: 'Policy not found',
102
+ data: z.object({
103
+ policyId: z.string(),
104
+ type: z.string(),
105
+ }),
106
+ },
107
+ POLICY_INACTIVE: {
108
+ status: 409,
109
+ message: 'Policy is not active',
110
+ data: z.object({
111
+ policyId: z.string(),
112
+ type: z.string(),
113
+ }),
114
+ },
115
+ POLICY_CREATION_FAILED: {
116
+ status: 500,
117
+ message: 'Failed to create or find policy',
118
+ data: z.object({
119
+ type: z.string(),
120
+ }),
121
+ },
122
+ // Purpose errors
123
+ PURPOSE_CREATION_FAILED: {
124
+ status: 500,
125
+ message: 'Failed to create consent purpose',
126
+ data: z.object({
127
+ purposeCode: z.string(),
128
+ }),
129
+ },
130
+ // Transaction errors
131
+ CONSENT_CREATION_FAILED: {
132
+ status: 500,
133
+ message: 'Failed to create consent record',
134
+ data: z.object({
135
+ subjectId: z.string(),
136
+ domain: z.string(),
137
+ }),
138
+ },
139
+ })
140
+ .input(
141
+ z.discriminatedUnion('type', [
142
+ cookieBannerSchema,
143
+ policyBasedSchema,
144
+ otherConsentSchema,
145
+ ])
146
+ )
147
+ .output(
148
+ z.object({
149
+ id: z.string(),
150
+ subjectId: z.string().optional(),
151
+ externalSubjectId: z.string().optional(),
152
+ domainId: z.string(),
153
+ domain: z.string(),
154
+ type: PolicyTypeSchema,
155
+ status: z.string(),
156
+ recordId: z.string(),
157
+ metadata: z.record(z.unknown()).optional(),
158
+ givenAt: z.date(),
159
+ })
160
+ );