@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,111 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { createCORSOptions } from './cors';
3
+
4
+ describe('createCORSOptions (unit)', () => {
5
+ describe('configuration shape', () => {
6
+ it('returns expected defaults when no trustedOrigins provided', async () => {
7
+ const config = createCORSOptions();
8
+ expect(config.credentials).toBe(true);
9
+ expect(config.maxAge).toBe(600);
10
+ expect(config.allowHeaders).toEqual([
11
+ 'Content-Type',
12
+ 'Authorization',
13
+ 'x-request-id',
14
+ ]);
15
+ expect(config.methods).toEqual([
16
+ 'GET',
17
+ 'POST',
18
+ 'PUT',
19
+ 'DELETE',
20
+ 'PATCH',
21
+ 'OPTIONS',
22
+ ]);
23
+ // origin present -> echo
24
+ expect(await config.origin('http://localhost:3002')).toBe(
25
+ 'http://localhost:3002'
26
+ );
27
+ // no origin -> '*'
28
+ expect(await config.origin('')).toBe('*');
29
+ });
30
+ });
31
+
32
+ describe('wildcard "*"', () => {
33
+ it('allows any concrete origin and echoes it back', async () => {
34
+ const config = createCORSOptions(['*']);
35
+ expect(await config.origin('http://localhost:3002')).toBe(
36
+ 'http://localhost:3002'
37
+ );
38
+ // missing origin -> '*'
39
+ expect(await config.origin('')).toBe('*');
40
+ });
41
+ });
42
+
43
+ describe('specific origins', () => {
44
+ it('allows trusted origin and rejects untrusted', async () => {
45
+ const config = createCORSOptions(['http://localhost:3002']);
46
+ expect(await config.origin('http://localhost:3002')).toBe(
47
+ 'http://localhost:3002'
48
+ );
49
+ expect(await config.origin('http://malicious-site.com')).toBeNull();
50
+ });
51
+
52
+ it('treats localhost variants (ports, IPs) as trusted when "localhost" provided', async () => {
53
+ const config = createCORSOptions(['localhost']);
54
+ expect(await config.origin('http://localhost:1234')).toBe(
55
+ 'http://localhost:1234'
56
+ );
57
+ expect(await config.origin('http://127.0.0.1:3000')).toBe(
58
+ 'http://127.0.0.1:3000'
59
+ );
60
+ expect(await config.origin('http://[::1]:3000')).toBe(
61
+ 'http://[::1]:3000'
62
+ );
63
+ });
64
+ });
65
+
66
+ describe('www and non-www variants', () => {
67
+ it('allows www when non-www is trusted', async () => {
68
+ const config = createCORSOptions(['http://c15t.com']);
69
+ expect(await config.origin('http://www.c15t.com')).toBe(
70
+ 'http://www.c15t.com'
71
+ );
72
+ });
73
+
74
+ it('allows non-www when www is trusted', async () => {
75
+ const config = createCORSOptions(['http://www.c15t.com']);
76
+ expect(await config.origin('http://c15t.com')).toBe('http://c15t.com');
77
+ });
78
+ });
79
+
80
+ describe('ports and protocols', () => {
81
+ it('matches with exact port when provided', async () => {
82
+ const config = createCORSOptions(['localhost:3002']);
83
+ expect(await config.origin('http://localhost:3002')).toBe(
84
+ 'http://localhost:3002'
85
+ );
86
+ expect(await config.origin('http://localhost:4000')).toBeNull();
87
+ });
88
+
89
+ it('is protocol-agnostic for host comparison', async () => {
90
+ const config = createCORSOptions(['example.com']);
91
+ expect(await config.origin('http://example.com')).toBe(
92
+ 'http://example.com'
93
+ );
94
+ expect(await config.origin('https://www.example.com')).toBe(
95
+ 'https://www.example.com'
96
+ );
97
+ });
98
+ });
99
+
100
+ describe('invalid or missing origins', () => {
101
+ it('returns null for clearly invalid origins', async () => {
102
+ const config = createCORSOptions(['example.com']);
103
+ expect(await config.origin('::::invalid::::')).toBeNull();
104
+ });
105
+
106
+ it('returns "*" when origin header is missing/empty', async () => {
107
+ const config = createCORSOptions(['*']);
108
+ expect(await config.origin('')).toBe('*');
109
+ });
110
+ });
111
+ });
@@ -0,0 +1,192 @@
1
+ /**
2
+ * CORS middleware utility for c15t that handles origin validation and CORS headers
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ /** Regular expression to match www prefix in domain names */
8
+ const WWW_REGEX = /^www\./;
9
+
10
+ /** Regular expression to match protocol and www prefix in URLs */
11
+ const PROTOCOL_WWW_REGEX = /^https?:\/\/(www\.)?/;
12
+
13
+ /**
14
+ * Supported HTTP methods for CORS
15
+ */
16
+ const SUPPORTED_METHODS = [
17
+ 'GET',
18
+ 'POST',
19
+ 'PUT',
20
+ 'DELETE',
21
+ 'PATCH',
22
+ 'OPTIONS',
23
+ ] as const;
24
+
25
+ /**
26
+ * Supported headers for CORS requests
27
+ */
28
+ const SUPPORTED_HEADERS = [
29
+ 'Content-Type',
30
+ 'Authorization',
31
+ 'x-request-id',
32
+ ] as const;
33
+
34
+ /**
35
+ * CORS configuration options type
36
+ */
37
+ export interface CORSConfig {
38
+ /** Origin validation function */
39
+ origin: (origin: string) => Promise<string | null>;
40
+ /** Whether to allow credentials */
41
+ credentials: boolean;
42
+ /** Allowed headers */
43
+ allowHeaders: readonly string[];
44
+ /** Max age for preflight requests */
45
+ maxAge: number;
46
+ /** Allowed HTTP methods */
47
+ methods: readonly string[];
48
+ }
49
+
50
+ /**
51
+ * Default CORS configuration for unrestricted access
52
+ */
53
+ const DEFAULT_CORS_CONFIG: CORSConfig = {
54
+ origin: async (origin: string) => {
55
+ // For default config, always return the origin if it exists, or '*' if it doesn't
56
+ return await Promise.resolve(origin || '*');
57
+ },
58
+ credentials: true,
59
+ allowHeaders: SUPPORTED_HEADERS,
60
+ maxAge: 600,
61
+ methods: SUPPORTED_METHODS,
62
+ } as const;
63
+
64
+ /**
65
+ * Creates CORS options configuration for the c15t middleware
66
+ *
67
+ * @param trustedOrigins - Array of allowed origin patterns or single string. Can include wildcards ('*').
68
+ * If undefined, defaults to allowing all origins without credentials.
69
+ *
70
+ * @returns CORS configuration object with origin validation function and header settings
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * const corsOptions = createCORSOptions(['http://localhost:3000', 'https://example.com']);
75
+ * ```
76
+ *
77
+ * @throws {TypeError} When URL parsing fails in origin validation
78
+ */
79
+ export function createCORSOptions(
80
+ trustedOrigins?: string[] | string
81
+ ): CORSConfig {
82
+ // If trustedOrigins is undefined or empty, return default config that allows all origins
83
+ if (!trustedOrigins) {
84
+ return DEFAULT_CORS_CONFIG;
85
+ }
86
+
87
+ // Convert string to array if needed
88
+ const origins = Array.isArray(trustedOrigins)
89
+ ? trustedOrigins
90
+ : [trustedOrigins];
91
+ if (origins.length === 0) {
92
+ return DEFAULT_CORS_CONFIG;
93
+ }
94
+
95
+ /**
96
+ * Normalizes an origin string by removing protocol and www prefix
97
+ *
98
+ * @param origin - The origin URL to normalize
99
+ * @returns Normalized origin string without protocol and www prefix
100
+ *
101
+ * @internal
102
+ */
103
+ function normalizeOrigin(origin: string): string {
104
+ try {
105
+ // Handle bare domains like 'localhost' or 'example.com'
106
+ if (
107
+ !origin.includes('://') &&
108
+ !origin.includes(':') &&
109
+ !origin.includes('/')
110
+ ) {
111
+ return origin.toLowerCase();
112
+ }
113
+ // Add protocol if missing
114
+ const originWithProtocol =
115
+ origin.startsWith('http://') ||
116
+ origin.startsWith('https://') ||
117
+ origin.startsWith('ws://') ||
118
+ origin.startsWith('wss://')
119
+ ? origin
120
+ : `http://${origin}`;
121
+ const url = new URL(originWithProtocol);
122
+ const hostname = url.hostname.replace(WWW_REGEX, '');
123
+ // Return without protocol to match both http and https
124
+ return `${hostname}${url.port ? `:${url.port}` : ''}`;
125
+ } catch {
126
+ // Fallback: remove www manually and protocol
127
+ return origin.replace(PROTOCOL_WWW_REGEX, '').replace(WWW_REGEX, '');
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Expands a list of origins to include www variants
133
+ *
134
+ * @param origins - Array of origin strings to expand
135
+ * @returns Array of origins including www variants
136
+ *
137
+ * @internal
138
+ */
139
+ function expandWithWWW(origins: string[]): string[] {
140
+ const expanded = new Set<string>();
141
+ for (const origin of origins) {
142
+ if (origin === '*') {
143
+ expanded.add('*');
144
+ continue;
145
+ }
146
+ const normalized = normalizeOrigin(origin);
147
+ expanded.add(normalized);
148
+ // Add www version if not already present
149
+ if (!normalized.includes('www.')) {
150
+ expanded.add(`www.${normalized}`);
151
+ }
152
+ }
153
+ return Array.from(expanded);
154
+ }
155
+
156
+ const expandedTrusted = expandWithWWW(origins);
157
+
158
+ const returnConfig = {
159
+ origin: async (origin: string) => {
160
+ if (!origin) {
161
+ return '*';
162
+ }
163
+ const normalizedOrigin = normalizeOrigin(origin);
164
+ if (expandedTrusted.includes('*')) {
165
+ return origin;
166
+ }
167
+ // Check if the origin matches any trusted origin
168
+ const isTrusted = expandedTrusted.some((trusted) => {
169
+ const normalizedTrusted = normalizeOrigin(trusted);
170
+ // For localhost, match both with and without port
171
+ if (normalizedTrusted === 'localhost') {
172
+ return (
173
+ normalizedOrigin === 'localhost' ||
174
+ normalizedOrigin.startsWith('localhost:') ||
175
+ normalizedOrigin === '127.0.0.1' ||
176
+ normalizedOrigin.startsWith('127.0.0.1:') ||
177
+ normalizedOrigin === '[::1]' ||
178
+ normalizedOrigin.startsWith('[::1]:')
179
+ );
180
+ }
181
+ return normalizedTrusted === normalizedOrigin;
182
+ });
183
+ return isTrusted ? origin : null;
184
+ },
185
+ credentials: true,
186
+ allowHeaders: SUPPORTED_HEADERS,
187
+ maxAge: 600,
188
+ methods: SUPPORTED_METHODS,
189
+ };
190
+
191
+ return returnConfig;
192
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * CORS middleware for c15t
3
+ *
4
+ * This module provides comprehensive CORS (Cross-Origin Resource Sharing) functionality including:
5
+ * - Origin validation with support for wildcards and subdomains
6
+ * - Flexible CORS options configuration
7
+ * - Context processing and enrichment
8
+ * - Protocol-agnostic matching
9
+ * - Support for www and non-www variants
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { createCORSOptions, isOriginTrusted, processCors } from '@c15t/backend/middleware/cors';
14
+ *
15
+ * // Create CORS options with trusted origins
16
+ * const corsOptions = createCORSOptions(['https://example.com', '*.trusted-domain.com']);
17
+ *
18
+ * // Process CORS for a request
19
+ * const enrichedContext = processCors(request, context, trustedOrigins);
20
+ *
21
+ * // Validate an origin directly
22
+ * const isTrusted = isOriginTrusted('https://api.trusted-domain.com', trustedOrigins);
23
+ * ```
24
+ *
25
+ * @packageDocumentation
26
+ */
27
+
28
+ export { createCORSOptions } from './cors';
29
+ export { isOriginTrusted } from './is-origin-trusted';
30
+ export { processCors } from './process-cors';
@@ -0,0 +1,104 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { isOriginTrusted } from './is-origin-trusted';
3
+
4
+ /**
5
+ * Test suite for CORS utility functions
6
+ */
7
+ describe('CORS utilities', () => {
8
+ describe('isOriginTrusted', () => {
9
+ it('should match exact origins', () => {
10
+ const trustedDomains = ['example.com'];
11
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(true);
12
+ expect(isOriginTrusted('https://other.com', trustedDomains)).toBe(false);
13
+ });
14
+
15
+ it('should handle origins with trailing slashes', () => {
16
+ const trustedDomains = ['example.com'];
17
+ expect(isOriginTrusted('https://example.com/', trustedDomains)).toBe(
18
+ true
19
+ );
20
+ expect(isOriginTrusted('https://example.com//', trustedDomains)).toBe(
21
+ true
22
+ );
23
+ });
24
+
25
+ it('should handle origins with paths', () => {
26
+ const trustedDomains = ['example.com'];
27
+ expect(isOriginTrusted('https://example.com/path', trustedDomains)).toBe(
28
+ true
29
+ );
30
+ expect(
31
+ isOriginTrusted('https://example.com/path/subpath', trustedDomains)
32
+ ).toBe(true);
33
+ });
34
+
35
+ it('should handle multiple trusted domains', () => {
36
+ const trustedDomains = ['example.com', 'test.com'];
37
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(true);
38
+ expect(isOriginTrusted('https://test.com', trustedDomains)).toBe(true);
39
+ expect(isOriginTrusted('https://other.com', trustedDomains)).toBe(false);
40
+ });
41
+
42
+ it('should handle wildcard subdomains', () => {
43
+ const trustedDomains = ['*.example.com'];
44
+ expect(isOriginTrusted('https://sub.example.com', trustedDomains)).toBe(
45
+ true
46
+ );
47
+ expect(
48
+ isOriginTrusted('https://other.sub.example.com', trustedDomains)
49
+ ).toBe(true);
50
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(
51
+ false
52
+ );
53
+ expect(isOriginTrusted('https://other.com', trustedDomains)).toBe(false);
54
+ });
55
+
56
+ it('should handle different protocols', () => {
57
+ const trustedDomains = ['example.com'];
58
+ expect(isOriginTrusted('http://example.com', trustedDomains)).toBe(true);
59
+ expect(isOriginTrusted('wss://example.com', trustedDomains)).toBe(true);
60
+ });
61
+
62
+ it('should handle ports in origins', () => {
63
+ const trustedDomains = ['example.com'];
64
+ expect(isOriginTrusted('https://example.com:3000', trustedDomains)).toBe(
65
+ true
66
+ );
67
+ expect(isOriginTrusted('http://example.com:8080', trustedDomains)).toBe(
68
+ true
69
+ );
70
+ });
71
+
72
+ it('should handle empty trusted domains array', () => {
73
+ const trustedDomains: string[] = [];
74
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(
75
+ false
76
+ );
77
+ });
78
+
79
+ it('should handle invalid origin formats', () => {
80
+ const trustedDomains = ['example.com'];
81
+ expect(isOriginTrusted('invalid-url', trustedDomains)).toBe(false);
82
+ expect(isOriginTrusted('', trustedDomains)).toBe(false);
83
+ });
84
+
85
+ it('should handle case sensitivity', () => {
86
+ const trustedDomains = ['EXAMPLE.com'];
87
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(true);
88
+ expect(isOriginTrusted('https://EXAMPLE.COM', trustedDomains)).toBe(true);
89
+ });
90
+
91
+ it('should handle subdomain levels with wildcards', () => {
92
+ const trustedDomains = ['*.example.com'];
93
+ expect(isOriginTrusted('https://a.b.example.com', trustedDomains)).toBe(
94
+ true
95
+ );
96
+ expect(isOriginTrusted('https://a.example.com', trustedDomains)).toBe(
97
+ true
98
+ );
99
+ expect(isOriginTrusted('https://example.com', trustedDomains)).toBe(
100
+ false
101
+ );
102
+ });
103
+ });
104
+ });
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Origin validation utilities for CORS security
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ import type { Logger } from '@doubletie/logger';
8
+
9
+ /**
10
+ * Regular expression to strip protocol, trailing slashes, and port numbers from URLs
11
+ * Matches:
12
+ * - http:// or https:// protocol
13
+ * - ws:// or wss:// protocol
14
+ * - trailing slashes
15
+ * - port numbers with colon
16
+ *
17
+ * @internal
18
+ */
19
+ export const STRIP_REGEX = /^(https?:\/\/)|(wss?:\/\/)|(\/+$)|:\d+/g;
20
+
21
+ /**
22
+ * Checks if a domain matches a wildcard pattern
23
+ *
24
+ * @param hostname - The hostname to check
25
+ * @param wildcardPattern - The wildcard pattern (e.g. *.example.com)
26
+ * @param logger - Optional logger for debugging
27
+ * @returns true if the hostname matches the wildcard pattern
28
+ *
29
+ * @internal
30
+ */
31
+ function matchesWildcard(
32
+ hostname: string,
33
+ wildcardPattern: string,
34
+ logger?: Logger
35
+ ): boolean {
36
+ const wildcardDomain = wildcardPattern.slice(2); // Remove *. prefix
37
+ const parts = hostname.split('.');
38
+ const isValid = parts.length > 2 && hostname.endsWith(wildcardDomain);
39
+
40
+ logger?.debug(
41
+ `Wildcard match result: ${isValid} ${hostname} ends with ${wildcardDomain} ${parts.length > 2} ${hostname.endsWith(wildcardDomain)}`
42
+ );
43
+
44
+ return isValid;
45
+ }
46
+
47
+ /**
48
+ * Validates if a given origin matches any of the trusted domain patterns
49
+ *
50
+ * Supports:
51
+ * - Exact domain matches
52
+ * - Wildcard subdomains (e.g. *.example.com)
53
+ * - Protocol-agnostic matching
54
+ * - Case-insensitive comparison
55
+ *
56
+ * @param origin - The origin URL to validate (e.g. https://example.com)
57
+ * @param trustedDomains - Array of trusted domain patterns. Can include wildcards (e.g. *.example.com)
58
+ * @param logger - Optional logger for debugging validation process
59
+ *
60
+ * @returns `true` if the origin matches any trusted domain pattern, `false` otherwise
61
+ *
62
+ * @throws {Error} When trustedDomains array is empty
63
+ * @throws {TypeError} When origin URL is invalid
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * // Simple domain matching
68
+ * isOriginTrusted('https://example.com', ['example.com']); // true
69
+ *
70
+ * // Wildcard subdomain matching
71
+ * isOriginTrusted('https://api.example.com', ['*.example.com']); // true
72
+ *
73
+ * // Allow all origins
74
+ * isOriginTrusted('https://any-domain.com', ['*']); // true
75
+ * ```
76
+ */
77
+ export function isOriginTrusted(
78
+ origin: string,
79
+ trustedDomains: string[],
80
+ logger?: Logger
81
+ ): boolean {
82
+ try {
83
+ if (trustedDomains.length === 0) {
84
+ throw new Error('No trusted domains');
85
+ }
86
+
87
+ logger?.debug(
88
+ `Checking if origin ${origin} is trusted in ${trustedDomains}`
89
+ );
90
+
91
+ // Special case: if "*" is in trusted domains, allow all origins
92
+ if (trustedDomains.includes('*')) {
93
+ logger?.debug('Allowing all origins');
94
+ return true;
95
+ }
96
+
97
+ // Parse the origin URL to get just the hostname
98
+ const url = new URL(origin);
99
+ const originHostname = url.hostname.toLowerCase();
100
+ logger?.debug(`Parsed origin hostname: ${originHostname}`);
101
+
102
+ return trustedDomains.some((domain) => {
103
+ // Handle empty domains (which might come from splitting empty strings)
104
+ if (!domain || domain.trim() === '') {
105
+ logger?.debug('Skipping empty domain');
106
+ return false;
107
+ }
108
+
109
+ const strippedDomain = domain.replace(STRIP_REGEX, '').toLowerCase();
110
+ logger?.debug(`Checking against stripped domain: ${strippedDomain}`);
111
+
112
+ if (strippedDomain.startsWith('*.')) {
113
+ return matchesWildcard(originHostname, strippedDomain, logger);
114
+ }
115
+
116
+ const isMatch = originHostname === strippedDomain;
117
+ logger?.debug(
118
+ `Exact match result: ${isMatch} ${originHostname} === ${strippedDomain}`
119
+ );
120
+ return isMatch;
121
+ });
122
+ } catch (error) {
123
+ logger?.error('Error validating origin:', error);
124
+ return false;
125
+ }
126
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * CORS processing middleware for c15t
3
+ * Handles origin validation and context enrichment
4
+ *
5
+ * @packageDocumentation
6
+ */
7
+
8
+ import type { C15TContext } from '~/v2/types';
9
+ import { isOriginTrusted } from './is-origin-trusted';
10
+
11
+ /**
12
+ * Result of CORS processing
13
+ * @internal
14
+ */
15
+ interface CORSProcessingResult {
16
+ /** The origin from the request */
17
+ origin: string | null;
18
+ /** Whether the origin is trusted */
19
+ isTrusted: boolean;
20
+ }
21
+
22
+ /**
23
+ * Extracts and validates CORS information from a request
24
+ *
25
+ * @param request - The request to process
26
+ * @param trustedOrigins - Array of trusted origins
27
+ * @param logger - Optional logger for debugging
28
+ * @returns CORS processing result
29
+ *
30
+ * @internal
31
+ */
32
+ function extractCORSInfo(
33
+ request: Request,
34
+ trustedOrigins?: string[],
35
+ logger?: C15TContext['logger']
36
+ ): CORSProcessingResult {
37
+ const origin = request.headers.get('origin');
38
+
39
+ if (!origin || !trustedOrigins) {
40
+ return {
41
+ origin: origin,
42
+ isTrusted: false,
43
+ };
44
+ }
45
+
46
+ return {
47
+ origin,
48
+ isTrusted: isOriginTrusted(origin, trustedOrigins, logger),
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Processes CORS validation for an incoming request and enriches the context
54
+ * with origin information. This middleware function validates the origin against
55
+ * trusted patterns and updates the context with the validation results.
56
+ *
57
+ * @param request - The incoming HTTP request to process
58
+ * @param context - The c15t middleware context to enrich
59
+ * @param trustedOrigins - Array of trusted origin patterns. Can include wildcards ('*')
60
+ *
61
+ * @returns The enriched context with origin validation results
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const enrichedContext = processCors(
66
+ * request,
67
+ * context,
68
+ * ['https://example.com', '*.trusted-domain.com']
69
+ * );
70
+ * ```
71
+ *
72
+ * @see {@link isOriginTrusted} for origin validation details
73
+ */
74
+ export const processCors = (
75
+ request: Request,
76
+ context: C15TContext,
77
+ trustedOrigins?: string[]
78
+ ): C15TContext => {
79
+ const { origin, isTrusted } = extractCORSInfo(
80
+ request,
81
+ trustedOrigins,
82
+ context.logger
83
+ );
84
+
85
+ if (origin) {
86
+ context.origin = origin;
87
+ context.trustedOrigin = isTrusted;
88
+ }
89
+
90
+ return context;
91
+ };
@@ -0,0 +1,27 @@
1
+ import type { C15TOptions } from '~/v2/types';
2
+ import { version } from '~/version';
3
+ /**
4
+ * Default OpenAPI configuration
5
+ */
6
+ export const createOpenAPIConfig = (options: C15TOptions) => {
7
+ const basePath = options.basePath || '';
8
+ return {
9
+ enabled: true,
10
+ specPath: `${basePath}/spec.json`,
11
+ docsPath: `${basePath}/docs`,
12
+ ...(options.advanced?.openapi || {}),
13
+ };
14
+ };
15
+
16
+ /**
17
+ * Default OpenAPI options
18
+ */
19
+ export const createDefaultOpenAPIOptions = (options: C15TOptions) => ({
20
+ info: {
21
+ title: options.appName || 'c15t API',
22
+ version,
23
+ description: 'API for consent management',
24
+ },
25
+ servers: [{ url: options.basePath || '/' }],
26
+ security: [{ bearerAuth: [] }],
27
+ });