@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,79 @@
1
+ import {
2
+ baseTranslations,
3
+ type CompleteTranslations,
4
+ deepMergeTranslations,
5
+ type Translations,
6
+ } from '@c15t/translations';
7
+
8
+ type SupportedBaseLanguage = keyof typeof baseTranslations;
9
+
10
+ function isSupportedBaseLanguage(lang: string): lang is SupportedBaseLanguage {
11
+ return lang in baseTranslations;
12
+ }
13
+
14
+ /**
15
+ * Extracts the preferred language from Accept-Language header
16
+ * Falls back to 'en' if no supported language is found
17
+ */
18
+ function getPreferredLanguage(
19
+ acceptLanguage: string | null,
20
+ supportedLanguages: string[]
21
+ ): string {
22
+ if (!acceptLanguage) {
23
+ return 'en';
24
+ }
25
+
26
+ // Get the primary language code
27
+ const primaryLang = acceptLanguage
28
+ .split(',')[0]
29
+ ?.split(';')[0]
30
+ ?.split('-')[0]
31
+ ?.toLowerCase();
32
+
33
+ // Check if it's a supported language
34
+ if (primaryLang && supportedLanguages.includes(primaryLang)) {
35
+ return primaryLang;
36
+ }
37
+
38
+ return 'en';
39
+ }
40
+
41
+ /**
42
+ * Gets the translations for a given language, merging custom translations if provided.
43
+ *
44
+ * @param acceptLanguage - The `Accept-Language` header from the request.
45
+ * @param customTranslations - An object containing custom translations to merge with the base translations.
46
+ * @returns An object containing the final translations and the determined language.
47
+ */
48
+ export function getTranslations(
49
+ acceptLanguage: string | null,
50
+ customTranslations?: Record<string, Partial<Translations>>
51
+ ) {
52
+ const supportedDefaultLanguages = Object.keys(baseTranslations);
53
+ const supportedCustomLanguages = Object.keys(customTranslations || {});
54
+
55
+ const supportedLanguages = [
56
+ ...supportedDefaultLanguages,
57
+ ...supportedCustomLanguages,
58
+ ];
59
+
60
+ const preferredLanguage = getPreferredLanguage(
61
+ acceptLanguage,
62
+ supportedLanguages
63
+ );
64
+
65
+ const base = isSupportedBaseLanguage(preferredLanguage)
66
+ ? baseTranslations[preferredLanguage]
67
+ : baseTranslations.en;
68
+
69
+ const custom = supportedCustomLanguages.includes(preferredLanguage)
70
+ ? customTranslations?.[preferredLanguage]
71
+ : {};
72
+
73
+ const translations = custom ? deepMergeTranslations(base, custom) : base;
74
+
75
+ return {
76
+ translations: translations as CompleteTranslations,
77
+ language: preferredLanguage,
78
+ };
79
+ }
@@ -0,0 +1,288 @@
1
+ import { ORPCError } from '@orpc/server';
2
+ import type { z } from 'zod';
3
+ import { os } from '~/v2/contracts';
4
+ import type { PolicyTypeSchema } from '~/v2/db/schema';
5
+ import type { C15TContext } from '~/v2/types';
6
+
7
+ /**
8
+ * Type representing a consent record with required fields
9
+ */
10
+ interface Consent {
11
+ id: string;
12
+ purposeIds: string[];
13
+ [key: string]: unknown;
14
+ }
15
+
16
+ /**
17
+ * Input type for verifying consent
18
+ */
19
+ type VerifyConsentInput = {
20
+ subjectId?: string;
21
+ externalSubjectId?: string;
22
+ domain: string;
23
+ type: z.infer<typeof PolicyTypeSchema>;
24
+ policyId?: string;
25
+ preferences?: string[];
26
+ };
27
+
28
+ /**
29
+ * Response type for consent verification
30
+ */
31
+ type VerifyConsentOutput = {
32
+ isValid: boolean;
33
+ reasons?: string[];
34
+ consent?: Consent;
35
+ };
36
+
37
+ /**
38
+ * Parameters for checking policy consent
39
+ */
40
+ interface PolicyConsentCheckParams {
41
+ policyId: string;
42
+ subjectId: string;
43
+ domainId: string;
44
+ purposeIds?: string[];
45
+ type: z.infer<typeof PolicyTypeSchema>;
46
+ context: C15TContext;
47
+ }
48
+
49
+ /**
50
+ * Handles verification of consent records.
51
+ *
52
+ * This handler checks if a subject has given valid consent for a specific policy
53
+ * and domain, optionally verifying specific purpose preferences.
54
+ *
55
+ * @throws {ORPCError} When:
56
+ * - Subject creation fails
57
+ * - Domain is not found
58
+ * - Policy is not found or invalid
59
+ * - Database query fails
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * // Verify cookie banner consent
64
+ * const response = await verifyConsent({
65
+ * type: 'cookie_banner',
66
+ * domain: 'example.com',
67
+ * preferences: ['analytics', 'marketing']
68
+ * });
69
+ * ```
70
+ */
71
+ export const verifyConsent = os.consent.verify.handler(
72
+ async ({ input, context }) => {
73
+ const typedContext = context as C15TContext;
74
+ const logger = typedContext.logger;
75
+ logger.info('Handling verify-consent request');
76
+
77
+ const {
78
+ type,
79
+ subjectId,
80
+ externalSubjectId,
81
+ domain,
82
+ policyId,
83
+ preferences,
84
+ } = input as VerifyConsentInput;
85
+
86
+ logger.debug('Request parameters', {
87
+ type,
88
+ subjectId,
89
+ externalSubjectId,
90
+ domain,
91
+ policyId,
92
+ preferences,
93
+ });
94
+
95
+ try {
96
+ // Find domain
97
+ const domainRecord = await typedContext.registry.findDomainByName(domain);
98
+
99
+ if (!domainRecord) {
100
+ throw new ORPCError('DOMAIN_NOT_FOUND', {
101
+ data: {
102
+ domain,
103
+ },
104
+ });
105
+ }
106
+
107
+ // Find subject
108
+ const subject = await typedContext.registry.findOrCreateSubject({
109
+ subjectId,
110
+ externalSubjectId,
111
+ ipAddress: typedContext.ipAddress ?? 'unknown',
112
+ });
113
+
114
+ if (!subject) {
115
+ throw new ORPCError('SUBJECT_NOT_FOUND', {
116
+ data: {
117
+ subjectId,
118
+ externalSubjectId,
119
+ },
120
+ });
121
+ }
122
+
123
+ if (
124
+ type === 'cookie_banner' &&
125
+ (!preferences || preferences.length === 0)
126
+ ) {
127
+ // Validate preferences for cookie banner
128
+ throw new ORPCError('COOKIE_BANNER_PREFERENCES_REQUIRED', {
129
+ data: {
130
+ type: 'cookie_banner',
131
+ },
132
+ });
133
+ }
134
+
135
+ // Find purpose IDs if preferences are provided
136
+ const purposePromises = preferences?.map((purpose: string) =>
137
+ typedContext.registry.findOrCreateConsentPurposeByCode(purpose)
138
+ );
139
+
140
+ const rawPurposes = await Promise.all(purposePromises ?? []);
141
+
142
+ const purposeIds = rawPurposes
143
+ .filter(
144
+ (purpose): purpose is NonNullable<typeof purpose> => purpose !== null
145
+ )
146
+ .map((purpose) => purpose.id);
147
+
148
+ if (purposeIds.length !== (preferences?.length ?? 0)) {
149
+ throw new ORPCError('PURPOSES_NOT_FOUND', {
150
+ data: {
151
+ preferences: preferences ?? [],
152
+ foundPurposes: rawPurposes
153
+ .filter((p): p is NonNullable<typeof p> => p !== null)
154
+ .map((p) => p.code),
155
+ },
156
+ });
157
+ }
158
+
159
+ if (policyId) {
160
+ // Check policy consent
161
+ const policy =
162
+ await typedContext.registry.findConsentPolicyById(policyId);
163
+ if (!policy || policy.type !== type) {
164
+ throw new ORPCError('POLICY_NOT_FOUND', {
165
+ data: {
166
+ policyId,
167
+ type,
168
+ },
169
+ });
170
+ }
171
+
172
+ return await checkPolicyConsent({
173
+ policyId: policy.id,
174
+ subjectId: subject.id,
175
+ domainId: domainRecord.id,
176
+ purposeIds,
177
+ type,
178
+ context: typedContext,
179
+ });
180
+ }
181
+
182
+ // Check latest policy consent
183
+ const latestPolicy = await typedContext.registry.findOrCreatePolicy(type);
184
+ if (!latestPolicy) {
185
+ throw new ORPCError('POLICY_NOT_FOUND', {
186
+ data: {
187
+ policyId: 'latest',
188
+ type,
189
+ },
190
+ });
191
+ }
192
+
193
+ return await checkPolicyConsent({
194
+ policyId: latestPolicy.id,
195
+ subjectId: subject.id,
196
+ domainId: domainRecord.id,
197
+ purposeIds,
198
+ type,
199
+ context: typedContext,
200
+ });
201
+ } catch (error) {
202
+ logger.error('Error in verify-consent handler', {
203
+ error: error instanceof Error ? error.message : String(error),
204
+ errorType:
205
+ error instanceof Error ? error.constructor.name : typeof error,
206
+ });
207
+
208
+ // Re-throw ORPCError instances
209
+ if (error instanceof ORPCError) {
210
+ throw error;
211
+ }
212
+
213
+ // Convert other errors to internal server error
214
+ throw new ORPCError('INTERNAL_SERVER_ERROR', {
215
+ message: error instanceof Error ? error.message : String(error),
216
+ });
217
+ }
218
+ }
219
+ );
220
+
221
+ /**
222
+ * Checks if consent has been given for a specific policy.
223
+ *
224
+ * @param params - Parameters for checking policy consent
225
+ * @returns Verification result with consent details if valid
226
+ *
227
+ * @throws {ORPCError} When database operations fail
228
+ */
229
+ async function checkPolicyConsent({
230
+ policyId,
231
+ subjectId,
232
+ domainId,
233
+ purposeIds,
234
+ type,
235
+ context,
236
+ }: PolicyConsentCheckParams): Promise<VerifyConsentOutput> {
237
+ const { registry, db } = context;
238
+
239
+ const rawConsents = await db.findMany('consent', {
240
+ where: (b) =>
241
+ b.and(
242
+ b('subjectId', '=', subjectId),
243
+ b('policyId', '=', policyId),
244
+ b('domainId', '=', domainId)
245
+ ),
246
+ orderBy: ['givenAt', 'desc'],
247
+ });
248
+
249
+ // Filter consents by purpose IDs if provided
250
+ const filteredConsents = rawConsents.filter((consent) => {
251
+ if (!purposeIds) {
252
+ return true;
253
+ }
254
+ return purposeIds.every((id) =>
255
+ (consent.purposeIds as string[]).some((purposeId) => purposeId === id)
256
+ );
257
+ });
258
+
259
+ await registry.createAuditLog({
260
+ subjectId,
261
+ entityType: 'consent_policy',
262
+ entityId: policyId,
263
+ actionType: 'verify_consent',
264
+ metadata: {
265
+ type,
266
+ policyId,
267
+ purposeIds,
268
+ success: filteredConsents.length !== 0,
269
+ ...(filteredConsents.length > 0
270
+ ? {
271
+ consentId: filteredConsents[0]?.id,
272
+ }
273
+ : {}),
274
+ },
275
+ eventTimezone: 'UTC',
276
+ });
277
+
278
+ if (rawConsents.length === 0 || filteredConsents.length === 0) {
279
+ return {
280
+ isValid: false,
281
+ };
282
+ }
283
+
284
+ return {
285
+ isValid: true,
286
+ consent: filteredConsents[0] as Consent,
287
+ };
288
+ }
@@ -0,0 +1,5 @@
1
+ import { statusHandler } from './status.handler';
2
+
3
+ export const metaHandlers = {
4
+ status: statusHandler,
5
+ };
@@ -0,0 +1,43 @@
1
+ import { os } from '~/v2/contracts';
2
+ import type { C15TContext } from '~/v2/types';
3
+ import { version } from '~/version';
4
+
5
+ // Use os.meta.status.handler to connect to the contract
6
+ export const statusHandler = os.meta.status.handler(({ context }) => {
7
+ const typedContext = context as C15TContext;
8
+
9
+ // Extract country and region from request headers
10
+ const headers = typedContext.headers;
11
+ const normalizeHeader = (
12
+ value: string | string[] | null | undefined
13
+ ): string | null => {
14
+ if (!value) {
15
+ return null;
16
+ }
17
+ return Array.isArray(value) ? (value[0] ?? null) : value;
18
+ };
19
+
20
+ const countryCode =
21
+ normalizeHeader(headers?.get('cf-ipcountry')) ??
22
+ normalizeHeader(headers?.get('x-vercel-ip-country')) ??
23
+ normalizeHeader(headers?.get('x-amz-cf-ipcountry')) ??
24
+ normalizeHeader(headers?.get('x-country-code'));
25
+
26
+ const regionCode =
27
+ normalizeHeader(headers?.get('x-vercel-ip-country-region')) ??
28
+ normalizeHeader(headers?.get('x-region-code'));
29
+
30
+ return {
31
+ status: 'ok' as const,
32
+ version,
33
+ timestamp: new Date(),
34
+ client: {
35
+ ip: typedContext.ipAddress ?? null,
36
+ userAgent: typedContext.userAgent ?? null,
37
+ region: {
38
+ countryCode,
39
+ regionCode,
40
+ },
41
+ },
42
+ };
43
+ });
@@ -0,0 +1,114 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+ import type { C15TOptions } from './types';
3
+
4
+ // Mock OpenTelemetry modules before any imports
5
+ vi.mock('@opentelemetry/sdk-node', () => ({
6
+ NodeSDK: vi.fn().mockImplementation(() => ({
7
+ start: vi.fn(),
8
+ })),
9
+ }));
10
+
11
+ vi.mock('@opentelemetry/resources', () => ({
12
+ resourceFromAttributes: vi.fn().mockImplementation((attributes) => ({
13
+ attributes,
14
+ })),
15
+ }));
16
+
17
+ vi.mock('@opentelemetry/sdk-trace-base', () => ({
18
+ ConsoleSpanExporter: vi.fn().mockImplementation(() => ({})),
19
+ }));
20
+
21
+ // Mock local modules
22
+ vi.mock('./utils/logger', () => ({
23
+ initLogger: vi.fn().mockReturnValue({
24
+ debug: vi.fn(),
25
+ info: vi.fn(),
26
+ warn: vi.fn(),
27
+ error: vi.fn(),
28
+ }),
29
+ }));
30
+
31
+ vi.mock('./db/registry', () => ({
32
+ createRegistry: vi.fn().mockReturnValue({}),
33
+ }));
34
+
35
+ vi.mock('./db/schema', () => ({
36
+ DB: {
37
+ client: vi.fn().mockImplementation((adapter) => ({
38
+ orm: vi.fn().mockResolvedValue({ adapter }),
39
+ })),
40
+ },
41
+ }));
42
+
43
+ afterEach(() => {
44
+ vi.clearAllMocks();
45
+ });
46
+
47
+ interface SetupParams {
48
+ telemetryDisabled?: boolean;
49
+ appName?: string;
50
+ }
51
+
52
+ async function setup(params: SetupParams = {}) {
53
+ const { telemetryDisabled = false, appName } = params;
54
+
55
+ // Reset the module cache to ensure a fresh instance for every test run
56
+ vi.resetModules();
57
+
58
+ // Get the mocked modules
59
+ const { NodeSDK } = await import('@opentelemetry/sdk-node');
60
+ const { DB } = await import('./db/schema');
61
+
62
+ // Get the start mock from the NodeSDK instance
63
+ const startMock = vi.fn();
64
+ const nodeSDKMock = NodeSDK as any;
65
+ nodeSDKMock.mockImplementation(() => ({
66
+ start: startMock,
67
+ }));
68
+
69
+ const { init } = await import('./init');
70
+
71
+ const options: Record<string, unknown> = {
72
+ trustedOrigins: [],
73
+ advanced: {
74
+ telemetry: telemetryDisabled ? { disabled: true } : {},
75
+ },
76
+ database: {},
77
+ };
78
+
79
+ if (appName !== undefined) {
80
+ options.appName = appName;
81
+ }
82
+
83
+ const context = init(options as unknown as C15TOptions);
84
+
85
+ return {
86
+ context,
87
+ startMock,
88
+ clientMock: DB.client,
89
+ };
90
+ }
91
+
92
+ describe('init', () => {
93
+ it('uses "c15t" as default appName when none is provided', async () => {
94
+ const { context, clientMock } = await setup();
95
+ expect(context.appName).toBe('c15t');
96
+ expect(clientMock).toHaveBeenCalledTimes(1);
97
+ });
98
+
99
+ it('uses the provided appName', async () => {
100
+ const appName = 'MyAmazingApp';
101
+ const { context } = await setup({ appName });
102
+ expect(context.appName).toBe(appName);
103
+ });
104
+
105
+ it('initialises telemetry when telemetry is enabled', async () => {
106
+ const { startMock } = await setup();
107
+ expect(startMock).toHaveBeenCalledTimes(1);
108
+ });
109
+
110
+ it('does not initialise telemetry when disabled via options', async () => {
111
+ const { startMock } = await setup({ telemetryDisabled: true });
112
+ expect(startMock).not.toHaveBeenCalled();
113
+ });
114
+ });
package/src/v2/init.ts ADDED
@@ -0,0 +1,126 @@
1
+ import { resourceFromAttributes } from '@opentelemetry/resources';
2
+ import { NodeSDK } from '@opentelemetry/sdk-node';
3
+ import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
4
+ import type { C15TContext, C15TOptions } from '~/v2/types';
5
+ import { version as packageVersion } from '../version';
6
+ import { createRegistry } from './db/registry';
7
+ import { DB } from './db/schema';
8
+ import { createTelemetryOptions } from './utils/create-telemetry-options';
9
+ import { initLogger } from './utils/logger';
10
+
11
+ // SDK instance should be at module level for proper lifecycle management
12
+ let telemetrySdk: NodeSDK | undefined;
13
+
14
+ /**
15
+ * Initializes telemetry SDK with the provided configuration
16
+ *
17
+ * @param appName - The application name for telemetry service identification
18
+ * @param telemetryOptions - Telemetry configuration options
19
+ * @param logger - Logger instance for telemetry status reporting
20
+ * @returns Whether telemetry was successfully initialized
21
+ */
22
+ const initializeTelemetry = (
23
+ appName: string,
24
+ telemetryOptions: ReturnType<typeof createTelemetryOptions>,
25
+ logger: ReturnType<typeof initLogger>
26
+ ): boolean => {
27
+ // Skip if SDK already initialized or telemetry is disabled
28
+ if (telemetrySdk) {
29
+ logger.debug('Telemetry SDK already initialized, skipping');
30
+ return true;
31
+ }
32
+
33
+ if (telemetryOptions?.disabled) {
34
+ logger.info('Telemetry is disabled by configuration');
35
+ return false;
36
+ }
37
+
38
+ try {
39
+ // Create a telemetry resource with provided values or safe defaults
40
+ const resource = resourceFromAttributes({
41
+ 'service.name': appName,
42
+ 'service.version': packageVersion,
43
+ ...(telemetryOptions?.defaultAttributes || {}),
44
+ });
45
+
46
+ logger.debug('Initializing telemetry with resource attributes', {
47
+ attributes: resource.attributes,
48
+ });
49
+
50
+ // Use provided tracer or fallback to console exporter
51
+ const traceExporter = telemetryOptions?.tracer
52
+ ? undefined // SDK will use the provided tracer
53
+ : new ConsoleSpanExporter();
54
+
55
+ // Create and start the SDK
56
+ telemetrySdk = new NodeSDK({
57
+ resource,
58
+ traceExporter,
59
+ });
60
+
61
+ telemetrySdk.start();
62
+ logger.info('Telemetry successfully initialized');
63
+ return true;
64
+ } catch (error) {
65
+ // Log the error but don't crash the application
66
+ logger.error('Telemetry initialization failed', {
67
+ error: error instanceof Error ? error.message : String(error),
68
+ stack: error instanceof Error ? error.stack : undefined,
69
+ });
70
+ logger.warn('Continuing without telemetry');
71
+ return false;
72
+ }
73
+ };
74
+
75
+ export const init = (options: C15TOptions): C15TContext => {
76
+ const appName = options.appName || 'c15t';
77
+
78
+ const logger = initLogger({
79
+ ...options.logger,
80
+ appName: String(appName),
81
+ });
82
+
83
+ // Create telemetry options
84
+ const telemetryOptions = createTelemetryOptions(
85
+ String(appName),
86
+ options.advanced?.telemetry
87
+ );
88
+
89
+ // Initialize telemetry
90
+ const telemetryInitialized = initializeTelemetry(
91
+ String(appName),
92
+ telemetryOptions,
93
+ logger
94
+ );
95
+
96
+ // Log final telemetry status
97
+ if (telemetryOptions?.disabled) {
98
+ logger.info('Telemetry is disabled by configuration');
99
+ } else if (telemetryInitialized) {
100
+ logger.info('Telemetry initialized successfully');
101
+ } else {
102
+ logger.warn(
103
+ 'Telemetry initialization failed, continuing without telemetry'
104
+ );
105
+ }
106
+
107
+ // Initialize core components
108
+ const client = DB.client(options.adapter);
109
+
110
+ const orm = client.orm('1.0.0');
111
+
112
+ const context: C15TContext = {
113
+ ...options,
114
+ appName,
115
+ logger,
116
+ db: orm,
117
+ registry: createRegistry({
118
+ db: orm,
119
+ ctx: {
120
+ logger,
121
+ },
122
+ }),
123
+ };
124
+
125
+ return context;
126
+ };