@c15t/backend 1.0.0 → 1.1.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/.turbo/turbo-build.log +33 -39
  2. package/.turbo/turbo-fmt.log +7 -0
  3. package/.turbo/turbo-test.log +531 -0
  4. package/README.md +19 -7
  5. package/coverage/coverage-final.json +84 -0
  6. package/coverage/coverage-summary.json +85 -0
  7. package/coverage/html/backend/index.html +116 -0
  8. package/coverage/html/backend/rslib.config.ts.html +415 -0
  9. package/coverage/html/backend/src/contracts/consent/index.html +161 -0
  10. package/coverage/html/backend/src/contracts/consent/index.ts.html +112 -0
  11. package/coverage/html/backend/src/contracts/consent/post.contract.ts.html +559 -0
  12. package/coverage/html/backend/src/contracts/consent/show-banner.contract.ts.html +220 -0
  13. package/coverage/html/backend/src/contracts/consent/verify.contract.ts.html +463 -0
  14. package/coverage/html/backend/src/contracts/index.html +116 -0
  15. package/coverage/html/backend/src/contracts/index.ts.html +139 -0
  16. package/coverage/html/backend/src/contracts/meta/index.html +131 -0
  17. package/coverage/html/backend/src/contracts/meta/index.ts.html +100 -0
  18. package/coverage/html/backend/src/contracts/meta/status.contract.ts.html +196 -0
  19. package/coverage/html/backend/src/contracts/shared/index.html +116 -0
  20. package/coverage/html/backend/src/contracts/shared/jurisdiction.schema.ts.html +175 -0
  21. package/coverage/html/backend/src/core.ts.html +1624 -0
  22. package/coverage/html/backend/src/handlers/consent/index.html +161 -0
  23. package/coverage/html/backend/src/handlers/consent/index.ts.html +112 -0
  24. package/coverage/html/backend/src/handlers/consent/post.handler.ts.html +889 -0
  25. package/coverage/html/backend/src/handlers/consent/show-banner.handler.ts.html +535 -0
  26. package/coverage/html/backend/src/handlers/consent/verify.handler.ts.html +1000 -0
  27. package/coverage/html/backend/src/handlers/meta/index.html +131 -0
  28. package/coverage/html/backend/src/handlers/meta/index.ts.html +100 -0
  29. package/coverage/html/backend/src/handlers/meta/status.handler.ts.html +226 -0
  30. package/coverage/html/backend/src/index.html +161 -0
  31. package/coverage/html/backend/src/init.ts.html +1018 -0
  32. package/coverage/html/backend/src/pkgs/api-router/hooks/index.html +116 -0
  33. package/coverage/html/backend/src/pkgs/api-router/hooks/processor.ts.html +544 -0
  34. package/coverage/html/backend/src/pkgs/api-router/index.html +116 -0
  35. package/coverage/html/backend/src/pkgs/api-router/telemetry.ts.html +334 -0
  36. package/coverage/html/backend/src/pkgs/api-router/utils/cors.ts.html +304 -0
  37. package/coverage/html/backend/src/pkgs/api-router/utils/index.html +131 -0
  38. package/coverage/html/backend/src/pkgs/api-router/utils/ip.ts.html +361 -0
  39. package/coverage/html/backend/src/pkgs/data-model/fields/field-factory.ts.html +709 -0
  40. package/coverage/html/backend/src/pkgs/data-model/fields/id-generator.ts.html +256 -0
  41. package/coverage/html/backend/src/pkgs/data-model/fields/index.html +161 -0
  42. package/coverage/html/backend/src/pkgs/data-model/fields/superjson-utils.ts.html +136 -0
  43. package/coverage/html/backend/src/pkgs/data-model/fields/zod-fields.ts.html +496 -0
  44. package/coverage/html/backend/src/pkgs/data-model/hooks/create-hooks.ts.html +349 -0
  45. package/coverage/html/backend/src/pkgs/data-model/hooks/index.html +176 -0
  46. package/coverage/html/backend/src/pkgs/data-model/hooks/update-hooks.ts.html +358 -0
  47. package/coverage/html/backend/src/pkgs/data-model/hooks/update-many-hooks.ts.html +613 -0
  48. package/coverage/html/backend/src/pkgs/data-model/hooks/utils.ts.html +538 -0
  49. package/coverage/html/backend/src/pkgs/data-model/hooks/with-hooks-factory.ts.html +289 -0
  50. package/coverage/html/backend/src/pkgs/db-adapters/adapter-factory.ts.html +289 -0
  51. package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts.html +2203 -0
  52. package/coverage/html/backend/src/pkgs/db-adapters/adapters/drizzle-adapter/index.html +116 -0
  53. package/coverage/html/backend/src/pkgs/db-adapters/adapters/index.html +116 -0
  54. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/dialect.ts.html +670 -0
  55. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/index.html +131 -0
  56. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.ts.html +3634 -0
  57. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/index.html +116 -0
  58. package/coverage/html/backend/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts.html +1417 -0
  59. package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/index.html +116 -0
  60. package/coverage/html/backend/src/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.ts.html +2071 -0
  61. package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/index.html +116 -0
  62. package/coverage/html/backend/src/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.ts.html +1834 -0
  63. package/coverage/html/backend/src/pkgs/db-adapters/adapters/test.ts.html +316 -0
  64. package/coverage/html/backend/src/pkgs/db-adapters/index.html +131 -0
  65. package/coverage/html/backend/src/pkgs/db-adapters/utils.ts.html +238 -0
  66. package/coverage/html/backend/src/pkgs/migrations/get-migration.ts.html +343 -0
  67. package/coverage/html/backend/src/pkgs/migrations/get-schema/get-schema.ts.html +217 -0
  68. package/coverage/html/backend/src/pkgs/migrations/get-schema/index.html +146 -0
  69. package/coverage/html/backend/src/pkgs/migrations/get-schema/process-fields.ts.html +280 -0
  70. package/coverage/html/backend/src/pkgs/migrations/get-schema/process-tables.ts.html +289 -0
  71. package/coverage/html/backend/src/pkgs/migrations/index.html +176 -0
  72. package/coverage/html/backend/src/pkgs/migrations/migration-builders.ts.html +595 -0
  73. package/coverage/html/backend/src/pkgs/migrations/migration-execution.ts.html +301 -0
  74. package/coverage/html/backend/src/pkgs/migrations/schema-comparison.ts.html +694 -0
  75. package/coverage/html/backend/src/pkgs/migrations/type-mapping.ts.html +817 -0
  76. package/coverage/html/backend/src/pkgs/results/core/error-class.ts.html +976 -0
  77. package/coverage/html/backend/src/pkgs/results/core/error-codes.ts.html +703 -0
  78. package/coverage/html/backend/src/pkgs/results/core/index.html +146 -0
  79. package/coverage/html/backend/src/pkgs/results/core/tracing.ts.html +280 -0
  80. package/coverage/html/backend/src/pkgs/results/create-telemetry-options.ts.html +271 -0
  81. package/coverage/html/backend/src/pkgs/results/index.html +131 -0
  82. package/coverage/html/backend/src/pkgs/results/orpc-error-handler.ts.html +496 -0
  83. package/coverage/html/backend/src/pkgs/results/results/index.html +131 -0
  84. package/coverage/html/backend/src/pkgs/results/results/recovery-utils.ts.html +628 -0
  85. package/coverage/html/backend/src/pkgs/results/results/result-helpers.ts.html +1234 -0
  86. package/coverage/html/backend/src/pkgs/utils/env.ts.html +337 -0
  87. package/coverage/html/backend/src/pkgs/utils/index.html +146 -0
  88. package/coverage/html/backend/src/pkgs/utils/logger.ts.html +199 -0
  89. package/coverage/html/backend/src/pkgs/utils/url.ts.html +400 -0
  90. package/coverage/html/backend/src/router.ts.html +109 -0
  91. package/coverage/html/backend/src/schema/audit-log/index.html +146 -0
  92. package/coverage/html/backend/src/schema/audit-log/registry.ts.html +436 -0
  93. package/coverage/html/backend/src/schema/audit-log/schema.ts.html +223 -0
  94. package/coverage/html/backend/src/schema/audit-log/table.ts.html +640 -0
  95. package/coverage/html/backend/src/schema/consent/index.html +146 -0
  96. package/coverage/html/backend/src/schema/consent/registry.ts.html +616 -0
  97. package/coverage/html/backend/src/schema/consent/schema.ts.html +238 -0
  98. package/coverage/html/backend/src/schema/consent/table.ts.html +748 -0
  99. package/coverage/html/backend/src/schema/consent-policy/index.html +146 -0
  100. package/coverage/html/backend/src/schema/consent-policy/registry.ts.html +1063 -0
  101. package/coverage/html/backend/src/schema/consent-policy/schema.ts.html +265 -0
  102. package/coverage/html/backend/src/schema/consent-policy/table.ts.html +535 -0
  103. package/coverage/html/backend/src/schema/consent-purpose/index.html +146 -0
  104. package/coverage/html/backend/src/schema/consent-purpose/registry.ts.html +589 -0
  105. package/coverage/html/backend/src/schema/consent-purpose/schema.ts.html +259 -0
  106. package/coverage/html/backend/src/schema/consent-purpose/table.ts.html +547 -0
  107. package/coverage/html/backend/src/schema/consent-record/index.html +131 -0
  108. package/coverage/html/backend/src/schema/consent-record/schema.ts.html +211 -0
  109. package/coverage/html/backend/src/schema/consent-record/table.ts.html +457 -0
  110. package/coverage/html/backend/src/schema/create-registry.ts.html +148 -0
  111. package/coverage/html/backend/src/schema/definition.ts.html +685 -0
  112. package/coverage/html/backend/src/schema/domain/index.html +146 -0
  113. package/coverage/html/backend/src/schema/domain/registry.ts.html +973 -0
  114. package/coverage/html/backend/src/schema/domain/schema.ts.html +214 -0
  115. package/coverage/html/backend/src/schema/domain/table.ts.html +496 -0
  116. package/coverage/html/backend/src/schema/index.html +146 -0
  117. package/coverage/html/backend/src/schema/schemas.ts.html +166 -0
  118. package/coverage/html/backend/src/schema/subject/index.html +146 -0
  119. package/coverage/html/backend/src/schema/subject/registry.ts.html +973 -0
  120. package/coverage/html/backend/src/schema/subject/schema.ts.html +208 -0
  121. package/coverage/html/backend/src/schema/subject/table.ts.html +499 -0
  122. package/coverage/html/backend/src/server.ts.html +475 -0
  123. package/coverage/html/backend/src/testing/contract-testing.ts.html +1348 -0
  124. package/coverage/html/backend/src/testing/index.html +116 -0
  125. package/coverage/html/base.css +224 -0
  126. package/coverage/html/block-navigation.js +87 -0
  127. package/coverage/html/favicon.png +0 -0
  128. package/coverage/html/index.html +626 -0
  129. package/coverage/html/prettify.css +1 -0
  130. package/coverage/html/prettify.js +2 -0
  131. package/coverage/html/sort-arrow-sprite.png +0 -0
  132. package/coverage/html/sorter.js +196 -0
  133. package/dist/contracts/consent/index.d.ts +401 -0
  134. package/dist/contracts/consent/index.d.ts.map +1 -0
  135. package/dist/contracts/consent/index.test.d.ts +2 -0
  136. package/dist/contracts/consent/index.test.d.ts.map +1 -0
  137. package/dist/contracts/consent/post.contract.d.ts +212 -0
  138. package/dist/contracts/consent/post.contract.d.ts.map +1 -0
  139. package/dist/contracts/consent/post.contract.test.d.ts +2 -0
  140. package/dist/contracts/consent/post.contract.test.d.ts.map +1 -0
  141. package/dist/contracts/consent/show-banner.contract.d.ts +45 -0
  142. package/dist/contracts/consent/show-banner.contract.d.ts.map +1 -0
  143. package/dist/contracts/consent/show-banner.contract.test.d.ts +2 -0
  144. package/dist/contracts/consent/show-banner.contract.test.d.ts.map +1 -0
  145. package/dist/contracts/consent/verify.contract.d.ts +147 -0
  146. package/dist/contracts/consent/verify.contract.d.ts.map +1 -0
  147. package/dist/contracts/consent/verify.contract.test.d.ts +2 -0
  148. package/dist/contracts/consent/verify.contract.test.d.ts.map +1 -0
  149. package/dist/contracts/index.d.ts +963 -0
  150. package/dist/contracts/index.d.ts.map +1 -0
  151. package/dist/contracts/meta/index.d.ts +78 -0
  152. package/dist/contracts/meta/index.d.ts.map +1 -0
  153. package/dist/contracts/meta/index.test.d.ts +2 -0
  154. package/dist/contracts/meta/index.test.d.ts.map +1 -0
  155. package/dist/contracts/meta/status.contract.d.ts +77 -0
  156. package/dist/contracts/meta/status.contract.d.ts.map +1 -0
  157. package/dist/contracts/meta/status.contract.test.d.ts +2 -0
  158. package/dist/contracts/meta/status.contract.test.d.ts.map +1 -0
  159. package/dist/contracts/shared/jurisdiction.schema.d.ts +24 -0
  160. package/dist/contracts/shared/jurisdiction.schema.d.ts.map +1 -0
  161. package/dist/core.cjs +3584 -0
  162. package/dist/core.d.ts +533 -78
  163. package/dist/core.d.ts.map +1 -1
  164. package/dist/{index.js → core.js} +1164 -1292
  165. package/dist/handlers/consent/index.d.ts +401 -0
  166. package/dist/handlers/consent/index.d.ts.map +1 -0
  167. package/dist/handlers/consent/post.handler.d.ts +234 -0
  168. package/dist/handlers/consent/post.handler.d.ts.map +1 -0
  169. package/dist/handlers/consent/show-banner.handler.d.ts +57 -0
  170. package/dist/handlers/consent/show-banner.handler.d.ts.map +1 -0
  171. package/dist/handlers/consent/show-banner.handler.test.d.ts +2 -0
  172. package/dist/handlers/consent/show-banner.handler.test.d.ts.map +1 -0
  173. package/dist/handlers/consent/verify.handler.d.ts +169 -0
  174. package/dist/handlers/consent/verify.handler.d.ts.map +1 -0
  175. package/dist/handlers/meta/index.d.ts +78 -0
  176. package/dist/handlers/meta/index.d.ts.map +1 -0
  177. package/dist/handlers/meta/status.handler.d.ts +76 -0
  178. package/dist/handlers/meta/status.handler.d.ts.map +1 -0
  179. package/dist/init.d.ts +0 -1
  180. package/dist/init.d.ts.map +1 -1
  181. package/dist/pkgs/api-router/hooks/processor.d.ts.map +1 -1
  182. package/dist/pkgs/api-router/types/router-props.d.ts +1 -1
  183. package/dist/pkgs/api-router/types/router-props.d.ts.map +1 -1
  184. package/dist/pkgs/api-router/utils/cors.d.ts +1 -1
  185. package/dist/pkgs/api-router/utils/cors.d.ts.map +1 -1
  186. package/dist/pkgs/data-model/fields/field-types.d.ts +1 -1
  187. package/dist/pkgs/data-model/fields/zod-fields.d.ts +32 -32
  188. package/dist/pkgs/data-model/index.cjs +1433 -1799
  189. package/dist/pkgs/data-model/index.js +20 -385
  190. package/dist/pkgs/data-model/schema/index.cjs +1402 -1768
  191. package/dist/pkgs/data-model/schema/index.js +20 -385
  192. package/dist/pkgs/db-adapters/adapter-factory.d.ts +2 -2
  193. package/dist/pkgs/db-adapters/adapter-factory.d.ts.map +1 -1
  194. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.d.ts +4 -7
  195. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.d.ts.map +1 -1
  196. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.cjs +19 -151
  197. package/dist/pkgs/db-adapters/adapters/drizzle-adapter/index.js +19 -151
  198. package/dist/pkgs/db-adapters/adapters/kysely-adapter/dialect.d.ts +1 -3
  199. package/dist/pkgs/db-adapters/adapters/kysely-adapter/dialect.d.ts.map +1 -1
  200. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.cjs +17 -149
  201. package/dist/pkgs/db-adapters/adapters/kysely-adapter/index.js +17 -149
  202. package/dist/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.d.ts +0 -1
  203. package/dist/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.d.ts.map +1 -1
  204. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts +2 -2
  205. package/dist/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.d.ts.map +1 -1
  206. package/dist/pkgs/db-adapters/adapters/kysely-adapter/types.d.ts +0 -2
  207. package/dist/pkgs/db-adapters/adapters/kysely-adapter/types.d.ts.map +1 -1
  208. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.cjs +17 -149
  209. package/dist/pkgs/db-adapters/adapters/memory-adapter/index.js +17 -149
  210. package/dist/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.d.ts +0 -1
  211. package/dist/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.d.ts.map +1 -1
  212. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.cjs +19 -151
  213. package/dist/pkgs/db-adapters/adapters/prisma-adapter/index.js +19 -151
  214. package/dist/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.d.ts +0 -1
  215. package/dist/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.d.ts.map +1 -1
  216. package/dist/pkgs/db-adapters/index.cjs +31 -153
  217. package/dist/pkgs/db-adapters/index.js +31 -153
  218. package/dist/pkgs/migrations/get-schema/get-schema.d.ts +2 -2
  219. package/dist/pkgs/migrations/get-schema/index.d.ts +1 -1
  220. package/dist/pkgs/migrations/index.cjs +30 -153
  221. package/dist/pkgs/migrations/index.js +30 -153
  222. package/dist/pkgs/migrations/schema-comparison.d.ts.map +1 -1
  223. package/dist/pkgs/results/core/error-class.d.ts +23 -21
  224. package/dist/pkgs/results/core/error-class.d.ts.map +1 -1
  225. package/dist/pkgs/results/index.cjs +17 -150
  226. package/dist/pkgs/results/index.d.ts +0 -3
  227. package/dist/pkgs/results/index.d.ts.map +1 -1
  228. package/dist/pkgs/results/index.js +17 -138
  229. package/dist/pkgs/results/orpc-error-handler.d.ts +65 -0
  230. package/dist/pkgs/results/orpc-error-handler.d.ts.map +1 -0
  231. package/dist/pkgs/results/types.d.ts +7 -7
  232. package/dist/pkgs/results/types.d.ts.map +1 -1
  233. package/dist/pkgs/types/context.d.ts +15 -8
  234. package/dist/pkgs/types/context.d.ts.map +1 -1
  235. package/dist/pkgs/types/endpoints.d.ts +3 -4
  236. package/dist/pkgs/types/endpoints.d.ts.map +1 -1
  237. package/dist/pkgs/types/options.d.ts +2 -4
  238. package/dist/pkgs/types/options.d.ts.map +1 -1
  239. package/dist/pkgs/types/plugins.d.ts +2 -3
  240. package/dist/pkgs/types/plugins.d.ts.map +1 -1
  241. package/dist/pkgs/utils/index.d.ts +1 -0
  242. package/dist/pkgs/utils/index.d.ts.map +1 -1
  243. package/dist/pkgs/utils/logger.d.ts +16 -0
  244. package/dist/pkgs/utils/logger.d.ts.map +1 -0
  245. package/dist/router.cjs +1213 -0
  246. package/dist/router.d.ts +480 -0
  247. package/dist/router.d.ts.map +1 -0
  248. package/dist/router.js +1169 -0
  249. package/dist/schema/audit-log/table.d.ts +1 -1
  250. package/dist/schema/consent/table.d.ts +1 -1
  251. package/dist/schema/consent-policy/registry.d.ts +12 -12
  252. package/dist/schema/consent-policy/schema.d.ts +6 -6
  253. package/dist/schema/consent-policy/table.d.ts +7 -7
  254. package/dist/schema/consent-purpose/registry.d.ts +6 -6
  255. package/dist/schema/consent-purpose/schema.d.ts +6 -6
  256. package/dist/schema/consent-purpose/table.d.ts +7 -7
  257. package/dist/schema/consent-record/table.d.ts +1 -1
  258. package/dist/schema/create-registry.d.ts +32 -32
  259. package/dist/schema/definition.d.ts +19 -19
  260. package/dist/schema/domain/registry.d.ts +10 -10
  261. package/dist/schema/domain/schema.d.ts +5 -5
  262. package/dist/schema/domain/table.d.ts +6 -6
  263. package/dist/schema/index.cjs +1409 -1775
  264. package/dist/schema/index.js +20 -385
  265. package/dist/schema/schemas.d.ts +19 -19
  266. package/dist/schema/subject/registry.d.ts +4 -4
  267. package/dist/schema/subject/schema.d.ts +2 -2
  268. package/dist/schema/subject/table.d.ts +3 -3
  269. package/dist/server.d.ts +2 -0
  270. package/dist/server.d.ts.map +1 -0
  271. package/dist/testing/contract-testing.d.ts +37 -0
  272. package/dist/testing/contract-testing.d.ts.map +1 -0
  273. package/dist/types/context.d.ts +1 -1
  274. package/dist/types/index.d.ts +2 -2
  275. package/dist/types/options.d.ts +33 -3
  276. package/dist/types/options.d.ts.map +1 -1
  277. package/dist/types/plugins.d.ts +3 -4
  278. package/dist/types/plugins.d.ts.map +1 -1
  279. package/package.json +20 -28
  280. package/rslib.config.ts +2 -5
  281. package/src/contracts/consent/index.test.ts +5 -0
  282. package/src/contracts/consent/index.ts +9 -0
  283. package/src/contracts/consent/post.contract.test.ts +526 -0
  284. package/src/contracts/consent/post.contract.ts +160 -0
  285. package/src/contracts/consent/show-banner.contract.test.ts +214 -0
  286. package/src/contracts/consent/show-banner.contract.ts +45 -0
  287. package/src/contracts/consent/verify.contract.test.ts +185 -0
  288. package/src/contracts/consent/verify.contract.ts +126 -0
  289. package/src/contracts/index.ts +18 -0
  290. package/src/contracts/meta/index.test.ts +5 -0
  291. package/src/contracts/meta/index.ts +5 -0
  292. package/src/contracts/meta/status.contract.test.ts +338 -0
  293. package/src/contracts/meta/status.contract.ts +37 -0
  294. package/src/contracts/shared/jurisdiction.schema.ts +30 -0
  295. package/src/core.ts +451 -161
  296. package/src/handlers/consent/index.ts +9 -0
  297. package/src/handlers/consent/post.handler.ts +273 -0
  298. package/src/handlers/consent/show-banner.handler.test.ts +148 -0
  299. package/src/handlers/consent/show-banner.handler.ts +150 -0
  300. package/src/handlers/consent/verify.handler.ts +305 -0
  301. package/src/handlers/meta/index.ts +5 -0
  302. package/src/handlers/meta/status.handler.ts +47 -0
  303. package/src/init.ts +8 -26
  304. package/src/pkgs/api-router/hooks/__tests__/processor.test.ts +6 -0
  305. package/src/pkgs/api-router/hooks/processor.ts +2 -0
  306. package/src/pkgs/api-router/types/router-props.ts +1 -1
  307. package/src/pkgs/api-router/utils/cors.ts +1 -1
  308. package/src/pkgs/data-model/fields/field-types.ts +1 -1
  309. package/src/pkgs/data-model/fields/id-generator.ts +1 -1
  310. package/src/pkgs/db-adapters/README.md +3 -3
  311. package/src/pkgs/db-adapters/adapter-factory.ts +8 -4
  312. package/src/pkgs/db-adapters/adapters/drizzle-adapter/drizzle-adapter.ts +13 -16
  313. package/src/pkgs/db-adapters/adapters/kysely-adapter/dialect.ts +1 -3
  314. package/src/pkgs/db-adapters/adapters/kysely-adapter/kysely-adapter.ts +0 -1
  315. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/postgres.test.ts +1 -1
  316. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/sqlite.test.ts +1 -1
  317. package/src/pkgs/db-adapters/adapters/kysely-adapter/tests/test-utils.ts +2 -2
  318. package/src/pkgs/db-adapters/adapters/kysely-adapter/types.ts +0 -2
  319. package/src/pkgs/db-adapters/adapters/memory-adapter/memory-adapter.ts +0 -1
  320. package/src/pkgs/db-adapters/adapters/prisma-adapter/prisma-adapter.ts +0 -1
  321. package/src/pkgs/migrations/get-migration.ts +3 -3
  322. package/src/pkgs/migrations/get-schema/get-schema.ts +2 -2
  323. package/src/pkgs/migrations/get-schema/index.ts +1 -1
  324. package/src/pkgs/migrations/migration-builders.ts +2 -2
  325. package/src/pkgs/migrations/migration-execution.ts +2 -2
  326. package/src/pkgs/migrations/schema-comparison.ts +5 -4
  327. package/src/pkgs/results/__tests__/error-class.test.ts +8 -7
  328. package/src/pkgs/results/core/error-class.ts +31 -43
  329. package/src/pkgs/results/index.ts +0 -10
  330. package/src/pkgs/results/orpc-error-handler.ts +137 -0
  331. package/src/pkgs/results/types.ts +8 -7
  332. package/src/pkgs/types/context.ts +18 -9
  333. package/src/pkgs/types/endpoints.ts +3 -5
  334. package/src/pkgs/types/options.ts +2 -4
  335. package/src/pkgs/types/plugins.ts +2 -3
  336. package/src/pkgs/utils/index.ts +1 -0
  337. package/src/pkgs/utils/logger.ts +38 -0
  338. package/src/router.ts +8 -0
  339. package/src/schema/audit-log/table.ts +1 -1
  340. package/src/schema/consent/table.ts +1 -1
  341. package/src/schema/consent-policy/table.ts +1 -1
  342. package/src/schema/consent-purpose/table.ts +1 -1
  343. package/src/schema/consent-record/table.ts +1 -1
  344. package/src/schema/definition.ts +2 -2
  345. package/src/schema/domain/table.ts +1 -1
  346. package/src/schema/subject/table.ts +1 -1
  347. package/src/server.ts +130 -0
  348. package/src/testing/contract-testing.ts +437 -0
  349. package/src/types/context.ts +1 -1
  350. package/src/types/index.ts +2 -2
  351. package/src/types/options.ts +38 -3
  352. package/src/types/plugins.ts +3 -4
  353. package/dist/index.cjs +0 -3706
  354. package/dist/index.d.ts +0 -11
  355. package/dist/index.d.ts.map +0 -1
  356. package/dist/init.test.d.ts +0 -2
  357. package/dist/init.test.d.ts.map +0 -1
  358. package/dist/integrations/cloudflare.cjs +0 -312
  359. package/dist/integrations/cloudflare.d.ts +0 -32
  360. package/dist/integrations/cloudflare.d.ts.map +0 -1
  361. package/dist/integrations/cloudflare.js +0 -278
  362. package/dist/integrations/next.cjs +0 -276
  363. package/dist/integrations/next.d.ts +0 -68
  364. package/dist/integrations/next.d.ts.map +0 -1
  365. package/dist/integrations/next.js +0 -239
  366. package/dist/integrations/node.cjs +0 -257
  367. package/dist/integrations/node.d.ts +0 -29
  368. package/dist/integrations/node.d.ts.map +0 -1
  369. package/dist/integrations/node.js +0 -223
  370. package/dist/pkgs/api-router/index.d.ts +0 -9
  371. package/dist/pkgs/api-router/index.d.ts.map +0 -1
  372. package/dist/pkgs/api-router/utils/define-route.d.ts +0 -87
  373. package/dist/pkgs/api-router/utils/define-route.d.ts.map +0 -1
  374. package/dist/pkgs/logger/__tests__/console-formatter.test.d.ts +0 -2
  375. package/dist/pkgs/logger/__tests__/console-formatter.test.d.ts.map +0 -1
  376. package/dist/pkgs/logger/__tests__/integration.test.d.ts +0 -2
  377. package/dist/pkgs/logger/__tests__/integration.test.d.ts.map +0 -1
  378. package/dist/pkgs/logger/__tests__/log-levels.test.d.ts +0 -2
  379. package/dist/pkgs/logger/__tests__/log-levels.test.d.ts.map +0 -1
  380. package/dist/pkgs/logger/__tests__/logger-factory.test.d.ts +0 -2
  381. package/dist/pkgs/logger/__tests__/logger-factory.test.d.ts.map +0 -1
  382. package/dist/pkgs/logger/__tests__/result-logging.test.d.ts +0 -2
  383. package/dist/pkgs/logger/__tests__/result-logging.test.d.ts.map +0 -1
  384. package/dist/pkgs/logger/__tests__/types.test.d.ts +0 -2
  385. package/dist/pkgs/logger/__tests__/types.test.d.ts.map +0 -1
  386. package/dist/pkgs/logger/console-formatter.d.ts +0 -56
  387. package/dist/pkgs/logger/console-formatter.d.ts.map +0 -1
  388. package/dist/pkgs/logger/index.cjs +0 -240
  389. package/dist/pkgs/logger/index.d.ts +0 -35
  390. package/dist/pkgs/logger/index.d.ts.map +0 -1
  391. package/dist/pkgs/logger/index.js +0 -185
  392. package/dist/pkgs/logger/log-levels.d.ts +0 -29
  393. package/dist/pkgs/logger/log-levels.d.ts.map +0 -1
  394. package/dist/pkgs/logger/logger-factory.d.ts +0 -42
  395. package/dist/pkgs/logger/logger-factory.d.ts.map +0 -1
  396. package/dist/pkgs/logger/result-logging.d.ts +0 -71
  397. package/dist/pkgs/logger/result-logging.d.ts.map +0 -1
  398. package/dist/pkgs/logger/telemetry.d.ts +0 -14
  399. package/dist/pkgs/logger/telemetry.d.ts.map +0 -1
  400. package/dist/pkgs/logger/types.d.ts +0 -121
  401. package/dist/pkgs/logger/types.d.ts.map +0 -1
  402. package/dist/pkgs/results/__tests__/retrieval-pipeline.test.d.ts +0 -2
  403. package/dist/pkgs/results/__tests__/retrieval-pipeline.test.d.ts.map +0 -1
  404. package/dist/pkgs/results/__tests__/validation-pipeline.test.d.ts +0 -2
  405. package/dist/pkgs/results/__tests__/validation-pipeline.test.d.ts.map +0 -1
  406. package/dist/pkgs/results/h3-integration.d.ts +0 -52
  407. package/dist/pkgs/results/h3-integration.d.ts.map +0 -1
  408. package/dist/pkgs/results/pipeline/retrieval-pipeline.d.ts +0 -101
  409. package/dist/pkgs/results/pipeline/retrieval-pipeline.d.ts.map +0 -1
  410. package/dist/pkgs/results/pipeline/validation-pipeline.d.ts +0 -89
  411. package/dist/pkgs/results/pipeline/validation-pipeline.d.ts.map +0 -1
  412. package/dist/response-types.d.ts +0 -19
  413. package/dist/response-types.d.ts.map +0 -1
  414. package/dist/routes/__test__/index.test.d.ts +0 -17
  415. package/dist/routes/__test__/index.test.d.ts.map +0 -1
  416. package/dist/routes/__test__/set-consent.test.d.ts +0 -2
  417. package/dist/routes/__test__/set-consent.test.d.ts.map +0 -1
  418. package/dist/routes/__test__/show-consent-banner.test.d.ts +0 -2
  419. package/dist/routes/__test__/show-consent-banner.test.d.ts.map +0 -1
  420. package/dist/routes/__test__/status.test.d.ts +0 -2
  421. package/dist/routes/__test__/status.test.d.ts.map +0 -1
  422. package/dist/routes/__test__/verify-consent.test.d.ts +0 -2
  423. package/dist/routes/__test__/verify-consent.test.d.ts.map +0 -1
  424. package/dist/routes/index.d.ts +0 -3
  425. package/dist/routes/index.d.ts.map +0 -1
  426. package/dist/routes/set-consent.d.ts +0 -89
  427. package/dist/routes/set-consent.d.ts.map +0 -1
  428. package/dist/routes/show-consent-banner.d.ts +0 -15
  429. package/dist/routes/show-consent-banner.d.ts.map +0 -1
  430. package/dist/routes/status.d.ts +0 -44
  431. package/dist/routes/status.d.ts.map +0 -1
  432. package/dist/routes/types.d.ts +0 -7
  433. package/dist/routes/types.d.ts.map +0 -1
  434. package/dist/routes/verify-consent.d.ts +0 -38
  435. package/dist/routes/verify-consent.d.ts.map +0 -1
  436. package/src/docs/ADVANCED_JSON_HANDLING.md +0 -99
  437. package/src/docs/neverthrow.md +0 -171
  438. package/src/index.ts +0 -34
  439. package/src/init.test.ts +0 -236
  440. package/src/integrations/cloudflare.ts +0 -269
  441. package/src/integrations/next.ts +0 -204
  442. package/src/integrations/node.ts +0 -141
  443. package/src/pkgs/api-router/index.ts +0 -148
  444. package/src/pkgs/api-router/types/h3.d.ts +0 -42
  445. package/src/pkgs/api-router/utils/define-route.ts +0 -410
  446. package/src/pkgs/logger/README.md +0 -213
  447. package/src/pkgs/logger/__tests__/console-formatter.test.ts +0 -67
  448. package/src/pkgs/logger/__tests__/integration.test.ts +0 -184
  449. package/src/pkgs/logger/__tests__/log-levels.test.ts +0 -77
  450. package/src/pkgs/logger/__tests__/logger-factory.test.ts +0 -156
  451. package/src/pkgs/logger/__tests__/result-logging.test.ts +0 -209
  452. package/src/pkgs/logger/__tests__/types.test.ts +0 -94
  453. package/src/pkgs/logger/console-formatter.ts +0 -75
  454. package/src/pkgs/logger/doc.md +0 -569
  455. package/src/pkgs/logger/index.ts +0 -59
  456. package/src/pkgs/logger/log-levels.ts +0 -46
  457. package/src/pkgs/logger/logger-factory.ts +0 -121
  458. package/src/pkgs/logger/result-logging.ts +0 -134
  459. package/src/pkgs/logger/telemetry.ts +0 -96
  460. package/src/pkgs/logger/types.ts +0 -138
  461. package/src/pkgs/results/__tests__/retrieval-pipeline.test.ts +0 -157
  462. package/src/pkgs/results/__tests__/validation-pipeline.test.ts +0 -151
  463. package/src/pkgs/results/h3-integration.ts +0 -142
  464. package/src/pkgs/results/pipeline/retrieval-pipeline.ts +0 -188
  465. package/src/pkgs/results/pipeline/validation-pipeline.ts +0 -164
  466. package/src/plugins/.keep +0 -0
  467. package/src/response-types.ts +0 -29
  468. package/src/routes/__test__/index.test.ts +0 -112
  469. package/src/routes/__test__/set-consent.test.ts +0 -242
  470. package/src/routes/__test__/show-consent-banner.test.ts +0 -98
  471. package/src/routes/__test__/status.test.ts +0 -64
  472. package/src/routes/__test__/verify-consent.test.ts +0 -266
  473. package/src/routes/index.ts +0 -12
  474. package/src/routes/set-consent.ts +0 -249
  475. package/src/routes/show-consent-banner.ts +0 -131
  476. package/src/routes/status.ts +0 -61
  477. package/src/routes/types.ts +0 -7
  478. package/src/routes/verify-consent.ts +0 -206
package/dist/core.cjs ADDED
@@ -0,0 +1,3584 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.n = (module)=>{
5
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
6
+ __webpack_require__.d(getter, {
7
+ a: getter
8
+ });
9
+ return getter;
10
+ };
11
+ })();
12
+ (()=>{
13
+ __webpack_require__.d = (exports1, definition)=>{
14
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
15
+ enumerable: true,
16
+ get: definition[key]
17
+ });
18
+ };
19
+ })();
20
+ (()=>{
21
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
22
+ })();
23
+ (()=>{
24
+ __webpack_require__.r = (exports1)=>{
25
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
26
+ value: 'Module'
27
+ });
28
+ Object.defineProperty(exports1, '__esModule', {
29
+ value: true
30
+ });
31
+ };
32
+ })();
33
+ var __webpack_exports__ = {};
34
+ __webpack_require__.r(__webpack_exports__);
35
+ __webpack_require__.d(__webpack_exports__, {
36
+ c15tInstance: ()=>c15tInstance
37
+ });
38
+ const logger_namespaceObject = require("@doubletie/logger");
39
+ const openapi_namespaceObject = require("@orpc/openapi");
40
+ const fetch_namespaceObject = require("@orpc/openapi/fetch");
41
+ const plugins_namespaceObject = require("@orpc/server/plugins");
42
+ const zod_namespaceObject = require("@orpc/zod");
43
+ const external_neverthrow_namespaceObject = require("neverthrow");
44
+ const server_namespaceObject = require("@orpc/server");
45
+ const error_codes_ERROR_CODES = Object.freeze({
46
+ NOT_FOUND: 'Resource not found',
47
+ BAD_REQUEST: 'Bad request',
48
+ CONFLICT: 'Conflict with current state',
49
+ MISSING_REQUIRED_PARAMETER: 'Missing required parameter',
50
+ UNAUTHORIZED: 'Unauthorized',
51
+ FORBIDDEN: 'Forbidden',
52
+ INTERNAL_SERVER_ERROR: 'Internal server error',
53
+ INITIALIZATION_FAILED: 'Initialization failed',
54
+ DATABASE_CONNECTION_ERROR: 'Database connection error',
55
+ DATABASE_QUERY_ERROR: 'Database query error',
56
+ INVALID_CONFIGURATION: 'Invalid configuration',
57
+ REQUEST_HANDLER_ERROR: 'Request handler error',
58
+ INVALID_REQUEST: 'Invalid request',
59
+ UNKNOWN_ERROR: 'Unknown error',
60
+ NETWORK_ERROR: 'Network error',
61
+ PLUGIN_INITIALIZATION_FAILED: 'Plugin initialization failed',
62
+ API_RETRIEVAL_ERROR: 'API retrieval error',
63
+ VALIDATION_ERROR: 'Validation error',
64
+ UNEXPECTED: 'Unexpected error'
65
+ });
66
+ const ERROR_CATEGORIES = Object.freeze({
67
+ VALIDATION: 'validation',
68
+ AUTHORIZATION: 'authorization',
69
+ STORAGE: 'storage',
70
+ NETWORK: 'network',
71
+ PLUGIN: 'plugin',
72
+ CONFIGURATION: 'configuration',
73
+ UNEXPECTED: 'unexpected'
74
+ });
75
+ const api_namespaceObject = require("@opentelemetry/api");
76
+ const tracing_tracer = api_namespaceObject.trace.getTracer('@doubletie/results');
77
+ async function tracing_withSpan(name, fn, attributes = {}) {
78
+ return await tracing_tracer.startActiveSpan(name, async (span)=>{
79
+ try {
80
+ span.setAttributes(attributes);
81
+ const result = await fn(span);
82
+ span.setStatus({
83
+ code: api_namespaceObject.SpanStatusCode.OK
84
+ });
85
+ span.end();
86
+ return result;
87
+ } catch (error) {
88
+ if (error instanceof error_class_DoubleTieError) {
89
+ span.setAttributes({
90
+ 'error.type': 'DoubleTieError',
91
+ 'error.code': error.code,
92
+ 'error.statusCode': error.statusCode,
93
+ 'error.message': error.message
94
+ });
95
+ if (error.meta) span.setAttributes({
96
+ 'error.meta': JSON.stringify(error.meta)
97
+ });
98
+ } else span.setAttributes({
99
+ 'error.type': error instanceof Error ? error.constructor.name : 'Unknown',
100
+ 'error.message': error instanceof Error ? error.message : String(error)
101
+ });
102
+ span.setStatus({
103
+ code: api_namespaceObject.SpanStatusCode.ERROR,
104
+ message: error instanceof Error ? error.message : String(error)
105
+ });
106
+ span.end();
107
+ throw error;
108
+ }
109
+ });
110
+ }
111
+ class error_class_DoubleTieError extends server_namespaceObject.ORPCError {
112
+ category;
113
+ meta;
114
+ statusCode;
115
+ constructor(message, options = {
116
+ code: error_codes_ERROR_CODES.UNKNOWN_ERROR,
117
+ status: 500,
118
+ category: ERROR_CATEGORIES.UNEXPECTED,
119
+ cause: void 0,
120
+ meta: {}
121
+ }){
122
+ super(options.code ?? error_codes_ERROR_CODES.UNKNOWN_ERROR, {
123
+ message,
124
+ cause: options.cause,
125
+ data: options.meta ?? {}
126
+ });
127
+ this.name = 'DoubleTieError';
128
+ this.category = options.category ?? ERROR_CATEGORIES.UNEXPECTED;
129
+ this.meta = options.meta ?? {};
130
+ this.statusCode = options.status ?? 500;
131
+ tracing_withSpan('create_doubletie_error', async (span)=>{
132
+ span.setAttributes({
133
+ 'error.name': this.constructor.name,
134
+ 'error.message': message,
135
+ 'error.code': this.code,
136
+ 'error.status': this.statusCode,
137
+ 'error.category': this.category,
138
+ 'error.has_cause': !!this.cause,
139
+ 'error.cause_type': this.cause instanceof Error ? this.cause.constructor.name : typeof this.cause,
140
+ 'error.has_meta': !!this.meta
141
+ });
142
+ if (this.cause instanceof Error) span.recordException(this.cause);
143
+ });
144
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
145
+ }
146
+ static isDoubleTieError(error) {
147
+ return error instanceof error_class_DoubleTieError;
148
+ }
149
+ toJSON() {
150
+ const validationErrorMessage = this.meta?.validationErrors ? String(this.meta.validationErrors) : void 0;
151
+ const stackTrace = this.stack ? this.stack.split('\n').map((line)=>line.trim()).filter((line)=>line && !line.includes('Error: ')) : [];
152
+ return {
153
+ code: this.code,
154
+ message: validationErrorMessage || this.message,
155
+ status: this.statusCode,
156
+ defined: true,
157
+ data: {
158
+ category: this.category,
159
+ meta: this.meta,
160
+ ...'production' === process.env.NODE_ENV ? {} : {
161
+ stack: stackTrace
162
+ },
163
+ ...validationErrorMessage && this.message ? {
164
+ originalMessage: this.message
165
+ } : {},
166
+ ...this.cause ? {
167
+ cause: this.cause instanceof Error ? {
168
+ name: this.cause.name,
169
+ message: this.cause.message,
170
+ stack: this.cause.stack ? this.cause.stack.split('\n').map((line)=>line.trim()) : void 0
171
+ } : this.cause
172
+ } : {}
173
+ }
174
+ };
175
+ }
176
+ static fromResponse(response, data) {
177
+ let message = `HTTP error ${response.status}`;
178
+ let errorCode = `HTTP ${response.status}`;
179
+ let errorMeta = {};
180
+ if (data && 'object' == typeof data && null !== data) {
181
+ const errorObj = data;
182
+ if ('string' == typeof errorObj.message) message = errorObj.message;
183
+ if ('string' == typeof errorObj.code) errorCode = errorObj.code;
184
+ if ('object' == typeof errorObj.data && null !== errorObj.data) errorMeta = errorObj.data;
185
+ }
186
+ return new error_class_DoubleTieError(message, {
187
+ code: errorCode,
188
+ status: response.status,
189
+ meta: errorMeta
190
+ });
191
+ }
192
+ withMeta(additionalMeta) {
193
+ return new error_class_DoubleTieError(this.message, {
194
+ code: this.code,
195
+ status: this.statusCode,
196
+ category: this.category,
197
+ cause: this.cause instanceof Error ? this.cause : void 0,
198
+ meta: {
199
+ ...this.meta,
200
+ ...additionalMeta
201
+ }
202
+ });
203
+ }
204
+ static createSubclass(name) {
205
+ const ErrorSubclass = class extends error_class_DoubleTieError {
206
+ constructor(message, options){
207
+ super(message, options);
208
+ Object.defineProperty(this, 'name', {
209
+ value: name
210
+ });
211
+ }
212
+ };
213
+ Object.defineProperty(ErrorSubclass, 'name', {
214
+ value: name
215
+ });
216
+ return ErrorSubclass;
217
+ }
218
+ static formatValidationError(error) {
219
+ if (!error.meta) return error.message;
220
+ let formattedMessage = `${error.message} (${error.code})`;
221
+ if (error.meta.validationErrors) formattedMessage += `\nValidation Errors: ${JSON.stringify(error.meta.validationErrors, null, 2)}`;
222
+ const otherMeta = Object.fromEntries(Object.entries(error.meta).filter(([key])=>'validationErrors' !== key));
223
+ if (Object.keys(otherMeta).length > 0) formattedMessage += `\nAdditional Context: ${JSON.stringify(otherMeta, null, 2)}`;
224
+ return formattedMessage;
225
+ }
226
+ }
227
+ function fail(message, options) {
228
+ const error = new error_class_DoubleTieError(message, options);
229
+ tracing_withSpan('create_error_result', async (span)=>{
230
+ span.setAttributes({
231
+ 'error.message': message,
232
+ 'error.code': options?.code,
233
+ 'error.status': options?.status,
234
+ 'error.category': options?.category
235
+ });
236
+ });
237
+ return (0, external_neverthrow_namespaceObject.err)(error);
238
+ }
239
+ function failAsync(message, options) {
240
+ const error = new error_class_DoubleTieError(message, options);
241
+ tracing_withSpan('create_error_result_async', async (span)=>{
242
+ span.setAttributes({
243
+ 'error.message': message,
244
+ 'error.code': options?.code,
245
+ 'error.status': options?.status,
246
+ 'error.category': options?.category
247
+ });
248
+ });
249
+ return (0, external_neverthrow_namespaceObject.errAsync)(error);
250
+ }
251
+ function promiseToResult(promise, errorCode = error_codes_ERROR_CODES.UNKNOWN_ERROR) {
252
+ return external_neverthrow_namespaceObject.ResultAsync.fromPromise(promise, (error)=>{
253
+ tracing_withSpan('promise_to_result', async (span)=>{
254
+ span.setAttributes({
255
+ 'operation.success': false,
256
+ 'error.type': error instanceof Error ? error.constructor.name : 'Unknown',
257
+ 'error.message': error instanceof Error ? error.message : String(error)
258
+ });
259
+ });
260
+ return new error_class_DoubleTieError(error instanceof Error ? error.message : String(error), {
261
+ code: errorCode,
262
+ cause: error instanceof Error ? error : void 0,
263
+ meta: {
264
+ error
265
+ }
266
+ });
267
+ }).map((result)=>{
268
+ tracing_withSpan('promise_to_result', async (span)=>{
269
+ span.setAttributes({
270
+ 'operation.success': true,
271
+ 'result.type': typeof result
272
+ });
273
+ });
274
+ return result;
275
+ });
276
+ }
277
+ function createTelemetryOptions(appName = 'c15t', telemetryConfig) {
278
+ const serviceVersion = process.env.npm_package_version || '1.0.0';
279
+ const config = {
280
+ disabled: telemetryConfig?.disabled ?? false,
281
+ tracer: telemetryConfig?.tracer,
282
+ defaultAttributes: {
283
+ ...telemetryConfig?.defaultAttributes || {},
284
+ 'service.name': String(appName),
285
+ 'service.version': serviceVersion
286
+ }
287
+ };
288
+ return config;
289
+ }
290
+ var package_namespaceObject = JSON.parse('{"i8":"1.1.0-canary.0"}');
291
+ const resources_namespaceObject = require("@opentelemetry/resources");
292
+ const sdk_node_namespaceObject = require("@opentelemetry/sdk-node");
293
+ const sdk_trace_base_namespaceObject = require("@opentelemetry/sdk-trace-base");
294
+ const external_defu_namespaceObject = require("defu");
295
+ function utils_applyDefaultValue(inputValue, field, operation) {
296
+ if ('update' === operation) return inputValue;
297
+ if (null == inputValue && field.defaultValue) {
298
+ if ('function' == typeof field.defaultValue) return field.defaultValue();
299
+ return field.defaultValue;
300
+ }
301
+ return inputValue;
302
+ }
303
+ const external_superjson_namespaceObject = require("superjson");
304
+ var external_superjson_default = /*#__PURE__*/ __webpack_require__.n(external_superjson_namespaceObject);
305
+ const COMMON_TIMEZONES = {
306
+ UTC: 'UTC',
307
+ GMT: 'GMT',
308
+ EASTERN: 'America/New_York',
309
+ CENTRAL: 'America/Chicago',
310
+ MOUNTAIN: 'America/Denver',
311
+ PACIFIC: 'America/Los_Angeles',
312
+ LONDON: 'Europe/London',
313
+ PARIS: 'Europe/Paris',
314
+ BERLIN: 'Europe/Berlin',
315
+ TOKYO: 'Asia/Tokyo',
316
+ SHANGHAI: 'Asia/Shanghai',
317
+ SINGAPORE: 'Asia/Singapore',
318
+ SYDNEY: 'Australia/Sydney',
319
+ SAO_PAULO: 'America/Sao_Paulo'
320
+ };
321
+ const external_base_x_namespaceObject = require("base-x");
322
+ var external_base_x_default = /*#__PURE__*/ __webpack_require__.n(external_base_x_namespaceObject);
323
+ const b58 = external_base_x_default()('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
324
+ function id_generator_generateId(prefix) {
325
+ const buf = crypto.getRandomValues(new Uint8Array(20));
326
+ const EPOCH_TIMESTAMP = 1700000000000;
327
+ const t = Date.now() - EPOCH_TIMESTAMP;
328
+ const high = Math.floor(t / 0x100000000);
329
+ const low = t >>> 0;
330
+ buf[0] = high >>> 24 & 255;
331
+ buf[1] = high >>> 16 & 255;
332
+ buf[2] = high >>> 8 & 255;
333
+ buf[3] = 255 & high;
334
+ buf[4] = low >>> 24 & 255;
335
+ buf[5] = low >>> 16 & 255;
336
+ buf[6] = low >>> 8 & 255;
337
+ buf[7] = 255 & low;
338
+ return `${prefix}_${b58.encode(buf)}`;
339
+ }
340
+ const external_zod_namespaceObject = require("zod");
341
+ const fieldConfigSchema = external_zod_namespaceObject.z.object({
342
+ required: external_zod_namespaceObject.z.boolean().default(true),
343
+ returned: external_zod_namespaceObject.z.boolean().default(true),
344
+ input: external_zod_namespaceObject.z.boolean().default(true),
345
+ defaultValue: external_zod_namespaceObject.z.union([
346
+ external_zod_namespaceObject.z.any(),
347
+ external_zod_namespaceObject.z["function"]().returns(external_zod_namespaceObject.z.any())
348
+ ]).optional(),
349
+ transform: external_zod_namespaceObject.z.object({
350
+ input: external_zod_namespaceObject.z["function"]().args(external_zod_namespaceObject.z.any()).returns(external_zod_namespaceObject.z.union([
351
+ external_zod_namespaceObject.z.any(),
352
+ external_zod_namespaceObject.z.promise(external_zod_namespaceObject.z.any())
353
+ ])).optional(),
354
+ output: external_zod_namespaceObject.z["function"]().args(external_zod_namespaceObject.z.any()).returns(external_zod_namespaceObject.z.union([
355
+ external_zod_namespaceObject.z.any(),
356
+ external_zod_namespaceObject.z.promise(external_zod_namespaceObject.z.any())
357
+ ])).optional()
358
+ }).optional(),
359
+ validator: external_zod_namespaceObject.z["function"]().args(external_zod_namespaceObject.z.any()).returns(external_zod_namespaceObject.z.union([
360
+ external_zod_namespaceObject.z.string(),
361
+ external_zod_namespaceObject.z["null"]()
362
+ ])).optional(),
363
+ unique: external_zod_namespaceObject.z.boolean().optional(),
364
+ indexed: external_zod_namespaceObject.z.boolean().optional(),
365
+ sortable: external_zod_namespaceObject.z.boolean().default(true),
366
+ fieldName: external_zod_namespaceObject.z.string().optional(),
367
+ bigint: external_zod_namespaceObject.z.boolean().default(false)
368
+ });
369
+ const stringFieldSchema = fieldConfigSchema.extend({
370
+ type: external_zod_namespaceObject.z.literal('string'),
371
+ minLength: external_zod_namespaceObject.z.number().optional(),
372
+ maxLength: external_zod_namespaceObject.z.number().optional(),
373
+ pattern: external_zod_namespaceObject.z.string().optional()
374
+ });
375
+ const numberFieldSchema = fieldConfigSchema.extend({
376
+ type: external_zod_namespaceObject.z.literal('number'),
377
+ min: external_zod_namespaceObject.z.number().optional(),
378
+ max: external_zod_namespaceObject.z.number().optional()
379
+ });
380
+ const booleanFieldSchema = fieldConfigSchema.extend({
381
+ type: external_zod_namespaceObject.z.literal('boolean')
382
+ });
383
+ const dateFieldSchema = fieldConfigSchema.extend({
384
+ type: external_zod_namespaceObject.z.literal('date'),
385
+ minDate: external_zod_namespaceObject.z.date().optional(),
386
+ maxDate: external_zod_namespaceObject.z.date().optional(),
387
+ dateOnly: external_zod_namespaceObject.z.boolean().default(false),
388
+ format: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional()
389
+ });
390
+ const timezoneFieldSchema = fieldConfigSchema.extend({
391
+ type: external_zod_namespaceObject.z.literal('timezone'),
392
+ validateTimezone: external_zod_namespaceObject.z.boolean().default(true),
393
+ suggestedValues: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()).optional(),
394
+ restrictToSuggestedValues: external_zod_namespaceObject.z.boolean().default(false)
395
+ });
396
+ const jsonFieldSchema = fieldConfigSchema.extend({
397
+ type: external_zod_namespaceObject.z.literal('json'),
398
+ validateJson: external_zod_namespaceObject.z.boolean().default(true)
399
+ });
400
+ const stringArrayFieldSchema = fieldConfigSchema.extend({
401
+ type: external_zod_namespaceObject.z.literal('string[]')
402
+ });
403
+ const numberArrayFieldSchema = fieldConfigSchema.extend({
404
+ type: external_zod_namespaceObject.z.literal('number[]')
405
+ });
406
+ external_zod_namespaceObject.z.discriminatedUnion('type', [
407
+ stringFieldSchema,
408
+ numberFieldSchema,
409
+ booleanFieldSchema,
410
+ dateFieldSchema,
411
+ timezoneFieldSchema,
412
+ jsonFieldSchema,
413
+ stringArrayFieldSchema,
414
+ numberArrayFieldSchema
415
+ ]);
416
+ const schema_auditLogSchema = external_zod_namespaceObject.z.object({
417
+ id: external_zod_namespaceObject.z.string(),
418
+ entityType: external_zod_namespaceObject.z.string(),
419
+ entityId: external_zod_namespaceObject.z.string(),
420
+ actionType: external_zod_namespaceObject.z.string(),
421
+ subjectId: external_zod_namespaceObject.z.string().optional(),
422
+ ipAddress: external_zod_namespaceObject.z.string().optional(),
423
+ userAgent: external_zod_namespaceObject.z.string().optional(),
424
+ changes: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional(),
425
+ metadata: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional(),
426
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date())
427
+ });
428
+ function getAuditLogTable(options, auditLogFields) {
429
+ const auditLogConfig = options.tables?.auditLog;
430
+ const subjectConfig = options.tables?.subject;
431
+ return {
432
+ entityName: auditLogConfig?.entityName || 'auditLog',
433
+ entityPrefix: auditLogConfig?.entityPrefix || 'log',
434
+ schema: schema_auditLogSchema,
435
+ fields: {
436
+ entityType: {
437
+ type: 'string',
438
+ required: true,
439
+ fieldName: auditLogConfig?.fields?.entityType || 'entityType'
440
+ },
441
+ entityId: {
442
+ type: 'string',
443
+ required: true,
444
+ fieldName: auditLogConfig?.fields?.entityId || 'entityId'
445
+ },
446
+ actionType: {
447
+ type: 'string',
448
+ required: true,
449
+ fieldName: auditLogConfig?.fields?.actionType || 'actionType'
450
+ },
451
+ subjectId: {
452
+ type: 'string',
453
+ required: false,
454
+ fieldName: auditLogConfig?.fields?.subjectId || 'subjectId',
455
+ references: {
456
+ model: subjectConfig?.entityName || 'subject',
457
+ field: 'id'
458
+ }
459
+ },
460
+ ipAddress: {
461
+ type: 'string',
462
+ required: false,
463
+ fieldName: auditLogConfig?.fields?.ipAddress || 'ipAddress'
464
+ },
465
+ userAgent: {
466
+ type: 'string',
467
+ required: false,
468
+ fieldName: auditLogConfig?.fields?.userAgent || 'userAgent'
469
+ },
470
+ changes: {
471
+ type: 'json',
472
+ required: false,
473
+ fieldName: auditLogConfig?.fields?.changes || 'changes'
474
+ },
475
+ metadata: {
476
+ type: 'json',
477
+ required: false,
478
+ fieldName: auditLogConfig?.fields?.metadata || 'metadata'
479
+ },
480
+ createdAt: {
481
+ type: 'date',
482
+ defaultValue: ()=>new Date(),
483
+ required: true,
484
+ fieldName: auditLogConfig?.fields?.createdAt || 'createdAt'
485
+ },
486
+ eventTimezone: {
487
+ type: 'timezone',
488
+ required: true,
489
+ defaultValue: COMMON_TIMEZONES.UTC,
490
+ fieldName: auditLogConfig?.fields?.eventTimezone || 'eventTimezone'
491
+ },
492
+ ...auditLogFields || {},
493
+ ...auditLogConfig?.additionalFields || {}
494
+ },
495
+ indexes: [
496
+ {
497
+ name: 'entity_index',
498
+ fields: [
499
+ 'entityType',
500
+ 'entityId'
501
+ ]
502
+ },
503
+ {
504
+ name: 'action_type_index',
505
+ fields: [
506
+ 'actionType'
507
+ ]
508
+ },
509
+ {
510
+ name: 'subject_id_index',
511
+ fields: [
512
+ 'subjectId'
513
+ ]
514
+ },
515
+ {
516
+ name: 'created_at_index',
517
+ fields: [
518
+ 'createdAt'
519
+ ]
520
+ }
521
+ ],
522
+ order: 5
523
+ };
524
+ }
525
+ const PolicyTypeSchema = external_zod_namespaceObject.z["enum"]([
526
+ 'cookie_banner',
527
+ 'privacy_policy',
528
+ 'dpa',
529
+ 'terms_and_conditions',
530
+ 'marketing_communications',
531
+ 'age_verification',
532
+ 'other'
533
+ ]);
534
+ const schema_consentPolicySchema = external_zod_namespaceObject.z.object({
535
+ id: external_zod_namespaceObject.z.string(),
536
+ version: external_zod_namespaceObject.z.string(),
537
+ type: PolicyTypeSchema,
538
+ name: external_zod_namespaceObject.z.string(),
539
+ effectiveDate: external_zod_namespaceObject.z.date(),
540
+ expirationDate: external_zod_namespaceObject.z.date().nullable().optional(),
541
+ content: external_zod_namespaceObject.z.string(),
542
+ contentHash: external_zod_namespaceObject.z.string(),
543
+ isActive: external_zod_namespaceObject.z.boolean().default(true),
544
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
545
+ updatedAt: external_zod_namespaceObject.z.date().default(()=>new Date())
546
+ });
547
+ function getConsentPolicyTable(options, policyFields) {
548
+ const consentPolicyConfig = options.tables?.consentPolicy;
549
+ return {
550
+ entityName: consentPolicyConfig?.entityName || 'consentPolicy',
551
+ entityPrefix: consentPolicyConfig?.entityPrefix || 'pol',
552
+ schema: schema_consentPolicySchema,
553
+ fields: {
554
+ version: {
555
+ type: 'string',
556
+ required: true,
557
+ fieldName: consentPolicyConfig?.fields?.version || 'version'
558
+ },
559
+ type: {
560
+ type: 'string',
561
+ required: true,
562
+ fieldName: consentPolicyConfig?.fields?.type || 'type'
563
+ },
564
+ name: {
565
+ type: 'string',
566
+ required: true,
567
+ fieldName: consentPolicyConfig?.fields?.name || 'name'
568
+ },
569
+ effectiveDate: {
570
+ type: 'date',
571
+ required: true,
572
+ fieldName: consentPolicyConfig?.fields?.effectiveDate || 'effectiveDate'
573
+ },
574
+ expirationDate: {
575
+ type: 'date',
576
+ required: false,
577
+ fieldName: consentPolicyConfig?.fields?.expirationDate || 'expirationDate'
578
+ },
579
+ content: {
580
+ type: 'string',
581
+ required: true,
582
+ fieldName: consentPolicyConfig?.fields?.content || 'content'
583
+ },
584
+ contentHash: {
585
+ type: 'string',
586
+ required: true,
587
+ fieldName: consentPolicyConfig?.fields?.contentHash || 'contentHash'
588
+ },
589
+ isActive: {
590
+ type: 'boolean',
591
+ defaultValue: true,
592
+ required: true,
593
+ fieldName: consentPolicyConfig?.fields?.isActive || 'isActive'
594
+ },
595
+ createdAt: {
596
+ type: 'date',
597
+ defaultValue: ()=>new Date(),
598
+ required: true,
599
+ fieldName: consentPolicyConfig?.fields?.createdAt || 'createdAt'
600
+ },
601
+ ...policyFields || {},
602
+ ...consentPolicyConfig?.additionalFields || {}
603
+ },
604
+ order: 2
605
+ };
606
+ }
607
+ const schema_purposeSchema = external_zod_namespaceObject.z.object({
608
+ id: external_zod_namespaceObject.z.string(),
609
+ code: external_zod_namespaceObject.z.string(),
610
+ name: external_zod_namespaceObject.z.string(),
611
+ description: external_zod_namespaceObject.z.string(),
612
+ isEssential: external_zod_namespaceObject.z.boolean().default(false),
613
+ dataCategory: external_zod_namespaceObject.z.string().optional(),
614
+ legalBasis: external_zod_namespaceObject.z.string().optional(),
615
+ isActive: external_zod_namespaceObject.z.boolean().default(true),
616
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
617
+ updatedAt: external_zod_namespaceObject.z.date().default(()=>new Date())
618
+ });
619
+ function getPurposeTable(options, purposeFields) {
620
+ const purposeConfig = options.tables?.consentPurpose;
621
+ return {
622
+ entityName: purposeConfig?.entityName || 'consentPurpose',
623
+ entityPrefix: purposeConfig?.entityPrefix || 'pur',
624
+ schema: schema_purposeSchema,
625
+ fields: {
626
+ code: {
627
+ type: 'string',
628
+ required: true,
629
+ fieldName: purposeConfig?.fields?.code || 'code'
630
+ },
631
+ name: {
632
+ type: 'string',
633
+ required: true,
634
+ fieldName: purposeConfig?.fields?.name || 'name'
635
+ },
636
+ description: {
637
+ type: 'string',
638
+ required: true,
639
+ fieldName: purposeConfig?.fields?.description || "description"
640
+ },
641
+ isEssential: {
642
+ type: 'boolean',
643
+ defaultValue: ()=>false,
644
+ required: true,
645
+ fieldName: purposeConfig?.fields?.isEssential || 'isEssential'
646
+ },
647
+ dataCategory: {
648
+ type: 'string',
649
+ required: false,
650
+ fieldName: purposeConfig?.fields?.dataCategory || 'dataCategory'
651
+ },
652
+ legalBasis: {
653
+ type: 'string',
654
+ required: false,
655
+ fieldName: purposeConfig?.fields?.legalBasis || 'legalBasis'
656
+ },
657
+ isActive: {
658
+ type: 'boolean',
659
+ defaultValue: true,
660
+ required: true,
661
+ fieldName: purposeConfig?.fields?.isActive || 'isActive'
662
+ },
663
+ createdAt: {
664
+ type: 'date',
665
+ defaultValue: ()=>new Date(),
666
+ required: true,
667
+ fieldName: purposeConfig?.fields?.createdAt || 'createdAt'
668
+ },
669
+ updatedAt: {
670
+ type: 'date',
671
+ defaultValue: ()=>new Date(),
672
+ required: true,
673
+ fieldName: purposeConfig?.fields?.updatedAt || 'updatedAt'
674
+ },
675
+ ...purposeFields || {},
676
+ ...purposeConfig?.additionalFields || {}
677
+ },
678
+ order: 1
679
+ };
680
+ }
681
+ const schema_consentRecordSchema = external_zod_namespaceObject.z.object({
682
+ id: external_zod_namespaceObject.z.string(),
683
+ subjectId: external_zod_namespaceObject.z.string(),
684
+ consentId: external_zod_namespaceObject.z.string().optional(),
685
+ actionType: external_zod_namespaceObject.z.string(),
686
+ details: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional(),
687
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
688
+ updatedAt: external_zod_namespaceObject.z.date().default(()=>new Date())
689
+ });
690
+ function getConsentRecordTable(options, recordFields) {
691
+ const recordConfig = options.tables?.record;
692
+ const subjectConfig = options.tables?.subject;
693
+ const consentConfig = options.tables?.consent;
694
+ return {
695
+ entityName: recordConfig?.entityName || 'consentRecord',
696
+ entityPrefix: recordConfig?.entityPrefix || 'rec',
697
+ schema: schema_consentRecordSchema,
698
+ fields: {
699
+ subjectId: {
700
+ type: 'string',
701
+ required: true,
702
+ fieldName: recordConfig?.fields?.subjectId || 'subjectId',
703
+ references: {
704
+ model: subjectConfig?.entityName || 'subject',
705
+ field: 'id'
706
+ }
707
+ },
708
+ consentId: {
709
+ type: 'string',
710
+ required: false,
711
+ fieldName: recordConfig?.fields?.consentId || 'consentId',
712
+ references: {
713
+ model: consentConfig?.entityName || 'consent',
714
+ field: 'id'
715
+ }
716
+ },
717
+ actionType: {
718
+ type: 'string',
719
+ required: true,
720
+ fieldName: recordConfig?.fields?.actionType || 'actionType'
721
+ },
722
+ details: {
723
+ type: 'json',
724
+ required: false,
725
+ fieldName: recordConfig?.fields?.details || 'details'
726
+ },
727
+ createdAt: {
728
+ type: 'date',
729
+ defaultValue: ()=>new Date(),
730
+ required: true,
731
+ fieldName: recordConfig?.fields?.createdAt || 'createdAt'
732
+ },
733
+ ...recordFields || {},
734
+ ...recordConfig?.additionalFields || {}
735
+ },
736
+ order: 4
737
+ };
738
+ }
739
+ const schema_consentSchema = external_zod_namespaceObject.z.object({
740
+ id: external_zod_namespaceObject.z.string(),
741
+ subjectId: external_zod_namespaceObject.z.string(),
742
+ domainId: external_zod_namespaceObject.z.string(),
743
+ purposeIds: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
744
+ metadata: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).nullable().optional(),
745
+ policyId: external_zod_namespaceObject.z.string().optional(),
746
+ ipAddress: external_zod_namespaceObject.z.string().nullable().optional(),
747
+ userAgent: external_zod_namespaceObject.z.string().nullable().optional(),
748
+ status: external_zod_namespaceObject.z["enum"]([
749
+ 'active',
750
+ 'withdrawn',
751
+ 'expired'
752
+ ]).default('active'),
753
+ withdrawalReason: external_zod_namespaceObject.z.string().nullable().optional(),
754
+ givenAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
755
+ validUntil: external_zod_namespaceObject.z.date().nullable().optional(),
756
+ isActive: external_zod_namespaceObject.z.boolean().default(true)
757
+ });
758
+ function getConsentTable(options, consentFields) {
759
+ const consentConfig = options.tables?.consent;
760
+ const subjectConfig = options.tables?.subject;
761
+ const domainConfig = options.tables?.domain;
762
+ const policyConfig = options.tables?.consentPolicy;
763
+ return {
764
+ entityName: consentConfig?.entityName || 'consent',
765
+ entityPrefix: consentConfig?.entityPrefix || 'cns',
766
+ schema: schema_consentSchema,
767
+ fields: {
768
+ subjectId: {
769
+ type: 'string',
770
+ required: true,
771
+ fieldName: consentConfig?.fields?.subjectId || 'subjectId',
772
+ references: {
773
+ model: subjectConfig?.entityName || 'subject',
774
+ field: 'id'
775
+ }
776
+ },
777
+ domainId: {
778
+ type: 'string',
779
+ required: true,
780
+ fieldName: consentConfig?.fields?.domainId || 'domainId',
781
+ references: {
782
+ model: domainConfig?.entityName || 'domain',
783
+ field: 'id'
784
+ }
785
+ },
786
+ purposeIds: {
787
+ type: 'json',
788
+ required: false,
789
+ fieldName: consentConfig?.fields?.purposeIds || 'purposeIds'
790
+ },
791
+ metadata: {
792
+ type: 'json',
793
+ required: false,
794
+ fieldName: consentConfig?.fields?.metadata || 'metadata'
795
+ },
796
+ policyId: {
797
+ type: 'string',
798
+ required: false,
799
+ fieldName: consentConfig?.fields?.policyId || 'policyId',
800
+ references: {
801
+ model: policyConfig?.entityName || 'consentPolicy',
802
+ field: 'id'
803
+ }
804
+ },
805
+ ipAddress: {
806
+ type: 'string',
807
+ required: false,
808
+ fieldName: consentConfig?.fields?.ipAddress || 'ipAddress'
809
+ },
810
+ userAgent: {
811
+ type: 'string',
812
+ required: false,
813
+ fieldName: consentConfig?.fields?.userAgent || 'userAgent'
814
+ },
815
+ status: {
816
+ type: 'string',
817
+ defaultValue: ()=>'active',
818
+ required: true,
819
+ fieldName: consentConfig?.fields?.status || 'status'
820
+ },
821
+ withdrawalReason: {
822
+ type: 'string',
823
+ required: false,
824
+ fieldName: consentConfig?.fields?.withdrawalReason || 'withdrawalReason'
825
+ },
826
+ givenAt: {
827
+ type: 'date',
828
+ defaultValue: ()=>new Date(),
829
+ required: true,
830
+ fieldName: consentConfig?.fields?.givenAt || 'givenAt'
831
+ },
832
+ validUntil: {
833
+ type: 'date',
834
+ required: false,
835
+ fieldName: consentConfig?.fields?.validUntil || 'validUntil',
836
+ transform: {
837
+ input: (val, data)=>{
838
+ if (val) return val;
839
+ const expiresIn = consentConfig?.expiresIn || 31536000;
840
+ const givenAt = data.givenAt instanceof Date ? data.givenAt : new Date();
841
+ if (expiresIn > 0) {
842
+ const validUntil = new Date(givenAt);
843
+ validUntil.setSeconds(validUntil.getSeconds() + expiresIn);
844
+ return validUntil;
845
+ }
846
+ }
847
+ }
848
+ },
849
+ isActive: {
850
+ type: 'boolean',
851
+ defaultValue: true,
852
+ required: true,
853
+ fieldName: consentConfig?.fields?.isActive || 'isActive'
854
+ },
855
+ ...consentFields || {},
856
+ ...consentConfig?.additionalFields || {}
857
+ },
858
+ order: 3
859
+ };
860
+ }
861
+ const schema_domainSchema = external_zod_namespaceObject.z.object({
862
+ id: external_zod_namespaceObject.z.string(),
863
+ name: external_zod_namespaceObject.z.string().min(1),
864
+ description: external_zod_namespaceObject.z.string().optional(),
865
+ allowedOrigins: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()).optional().default([]),
866
+ isVerified: external_zod_namespaceObject.z.boolean().default(true),
867
+ isActive: external_zod_namespaceObject.z.boolean().default(true),
868
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
869
+ updatedAt: external_zod_namespaceObject.z.date().default(()=>new Date())
870
+ });
871
+ function getDomainTable(options, domainFields) {
872
+ const domainConfig = options.tables?.domain;
873
+ return {
874
+ entityName: domainConfig?.entityName || 'domain',
875
+ entityPrefix: domainConfig?.entityPrefix || 'dom',
876
+ schema: schema_domainSchema,
877
+ fields: {
878
+ name: {
879
+ type: 'string',
880
+ required: true,
881
+ unique: true,
882
+ fieldName: domainConfig?.fields?.name || 'name'
883
+ },
884
+ description: {
885
+ type: 'string',
886
+ required: false,
887
+ fieldName: domainConfig?.fields?.description || "description"
888
+ },
889
+ allowedOrigins: {
890
+ type: 'json',
891
+ defaultValue: ()=>[],
892
+ required: false,
893
+ fieldName: domainConfig?.fields?.allowedOrigins || 'allowedOrigins'
894
+ },
895
+ isVerified: {
896
+ type: 'boolean',
897
+ defaultValue: true,
898
+ required: true,
899
+ fieldName: domainConfig?.fields?.isVerified || 'isVerified'
900
+ },
901
+ isActive: {
902
+ type: 'boolean',
903
+ defaultValue: true,
904
+ required: true,
905
+ fieldName: domainConfig?.fields?.isActive || 'isActive'
906
+ },
907
+ createdAt: {
908
+ type: 'date',
909
+ defaultValue: ()=>new Date(),
910
+ required: true,
911
+ fieldName: domainConfig?.fields?.createdAt || 'createdAt'
912
+ },
913
+ updatedAt: {
914
+ type: 'date',
915
+ required: false,
916
+ fieldName: domainConfig?.fields?.updatedAt || 'updatedAt'
917
+ },
918
+ ...domainFields || {},
919
+ ...domainConfig?.additionalFields || {}
920
+ },
921
+ order: 1
922
+ };
923
+ }
924
+ const schema_subjectSchema = external_zod_namespaceObject.z.object({
925
+ id: external_zod_namespaceObject.z.string(),
926
+ isIdentified: external_zod_namespaceObject.z.boolean().default(false),
927
+ externalId: external_zod_namespaceObject.z.string().nullable().optional(),
928
+ identityProvider: external_zod_namespaceObject.z.string().optional(),
929
+ lastIpAddress: external_zod_namespaceObject.z.string().optional(),
930
+ createdAt: external_zod_namespaceObject.z.date().default(()=>new Date()),
931
+ updatedAt: external_zod_namespaceObject.z.date().default(()=>new Date())
932
+ });
933
+ function getSubjectTable(options, subjectFields) {
934
+ const subjectConfig = options.tables?.subject;
935
+ return {
936
+ entityName: subjectConfig?.entityName || 'subject',
937
+ entityPrefix: subjectConfig?.entityPrefix || 'sub',
938
+ schema: schema_subjectSchema,
939
+ fields: {
940
+ isIdentified: {
941
+ type: 'boolean',
942
+ defaultValue: ()=>false,
943
+ required: true,
944
+ fieldName: subjectConfig?.fields?.isIdentified || 'isIdentified'
945
+ },
946
+ externalId: {
947
+ type: 'string',
948
+ required: false,
949
+ fieldName: subjectConfig?.fields?.externalId || 'externalId'
950
+ },
951
+ identityProvider: {
952
+ type: 'string',
953
+ required: false,
954
+ fieldName: subjectConfig?.fields?.identityProvider || 'identityProvider'
955
+ },
956
+ lastIpAddress: {
957
+ type: 'string',
958
+ required: false,
959
+ fieldName: subjectConfig?.fields?.lastIpAddress || 'lastIpAddress'
960
+ },
961
+ createdAt: {
962
+ type: 'date',
963
+ defaultValue: ()=>new Date(),
964
+ required: true,
965
+ fieldName: subjectConfig?.fields?.createdAt || 'createdAt'
966
+ },
967
+ updatedAt: {
968
+ type: 'date',
969
+ defaultValue: ()=>new Date(),
970
+ required: true,
971
+ fieldName: subjectConfig?.fields?.updatedAt || 'updatedAt'
972
+ },
973
+ subjectTimezone: {
974
+ type: 'timezone',
975
+ required: false,
976
+ defaultValue: COMMON_TIMEZONES.UTC,
977
+ fieldName: subjectConfig?.fields?.subjectTimezone || 'subjectTimezone'
978
+ },
979
+ ...subjectFields || {},
980
+ ...subjectConfig?.additionalFields || {}
981
+ },
982
+ order: 1
983
+ };
984
+ }
985
+ const definition_getConsentTables = (options)=>{
986
+ const pluginSchema = options.plugins?.reduce((acc, plugin)=>{
987
+ const schema = plugin.schema;
988
+ if (!schema) return acc;
989
+ for (const [key, value] of Object.entries(schema))acc[key] = {
990
+ fields: {
991
+ ...acc[key]?.fields,
992
+ ...value.fields
993
+ },
994
+ entityName: key
995
+ };
996
+ return acc;
997
+ }, {});
998
+ const { subject, consentPurpose, consentPolicy, domain, geoLocation, consent, consentPurposeJunction, record, consentGeoLocation, consentWithdrawal, auditLog, ...pluginTables } = pluginSchema || {};
999
+ return {
1000
+ subject: getSubjectTable(options, subject?.fields),
1001
+ consentPurpose: getPurposeTable(options, consentPurpose?.fields),
1002
+ consentPolicy: getConsentPolicyTable(options, consentPolicy?.fields),
1003
+ domain: getDomainTable(options, domain?.fields),
1004
+ consent: getConsentTable(options, consent?.fields),
1005
+ consentRecord: getConsentRecordTable(options, record?.fields),
1006
+ auditLog: getAuditLogTable(options, auditLog?.fields),
1007
+ ...pluginTables
1008
+ };
1009
+ };
1010
+ function validateEntityOutput(tableName, data, options) {
1011
+ const tables = definition_getConsentTables(options);
1012
+ const table = tables[tableName];
1013
+ if (!table) throw new Error(`Table ${tableName} not found`);
1014
+ const processedData = {
1015
+ ...data
1016
+ };
1017
+ for (const [field, def] of Object.entries(table.fields))if ('date' === def.type && 'string' == typeof processedData[field]) processedData[field] = new Date(processedData[field]);
1018
+ try {
1019
+ return table.schema.parse(processedData);
1020
+ } catch (error) {
1021
+ if (error instanceof external_zod_namespaceObject.ZodError) logger_namespaceObject.logger.error(`[validateEntityOutput] Validation failed for table ${String(tableName)}`, {
1022
+ table,
1023
+ issues: error.issues
1024
+ });
1025
+ throw error;
1026
+ }
1027
+ }
1028
+ function subjectRegistry({ adapter, ...ctx }) {
1029
+ const { createWithHooks } = getWithHooks(adapter, ctx);
1030
+ return {
1031
+ createSubject: async (subject, context)=>{
1032
+ const createdSubject = await createWithHooks({
1033
+ data: {
1034
+ createdAt: new Date(),
1035
+ updatedAt: new Date(),
1036
+ ...subject
1037
+ },
1038
+ model: 'subject',
1039
+ customFn: void 0,
1040
+ context
1041
+ });
1042
+ return createdSubject ? validateEntityOutput('subject', createdSubject, ctx.options) : null;
1043
+ },
1044
+ findOrCreateSubject: async function({ subjectId, externalSubjectId, ipAddress = 'unknown', context }) {
1045
+ if (subjectId && externalSubjectId) {
1046
+ const [subjectById, subjectByExternalId] = await Promise.all([
1047
+ this.findSubjectById(subjectId),
1048
+ this.findSubjectByExternalId(externalSubjectId)
1049
+ ]);
1050
+ if (!subjectById || !subjectByExternalId) {
1051
+ ctx.logger?.error('Subject validation failed: One or both subjects not found', {
1052
+ providedSubjectId: subjectId,
1053
+ providedExternalId: externalSubjectId,
1054
+ subjectByIdFound: !!subjectById,
1055
+ subjectByExternalIdFound: !!subjectByExternalId
1056
+ });
1057
+ throw new error_class_DoubleTieError('The specified subject could not be found. Please verify the subject identifiers and try again.', {
1058
+ code: error_codes_ERROR_CODES.NOT_FOUND,
1059
+ status: 404,
1060
+ meta: {
1061
+ providedSubjectId: subjectId,
1062
+ providedExternalId: externalSubjectId
1063
+ }
1064
+ });
1065
+ }
1066
+ if (subjectById.id !== subjectByExternalId.id) {
1067
+ ctx.logger?.warn('Subject validation failed: IDs do not match the same subject', {
1068
+ providedSubjectId: subjectId,
1069
+ providedExternalId: externalSubjectId,
1070
+ subjectByIdId: subjectById.id,
1071
+ subjectByExternalIdId: subjectByExternalId.id
1072
+ });
1073
+ throw new error_class_DoubleTieError('The provided subjectId and externalSubjectId do not match the same subject. Please ensure both identifiers refer to the same subject.', {
1074
+ code: error_codes_ERROR_CODES.CONFLICT,
1075
+ status: 409,
1076
+ meta: {
1077
+ providedSubjectId: subjectId,
1078
+ providedExternalId: externalSubjectId,
1079
+ subjectByIdId: subjectById.id,
1080
+ subjectByExternalIdId: subjectByExternalId.id
1081
+ }
1082
+ });
1083
+ }
1084
+ return subjectById;
1085
+ }
1086
+ if (subjectId) {
1087
+ const subject = await this.findSubjectById(subjectId);
1088
+ if (subject) return subject;
1089
+ throw new error_class_DoubleTieError('Subject not found by subjectId', {
1090
+ code: error_codes_ERROR_CODES.NOT_FOUND,
1091
+ status: 404
1092
+ });
1093
+ }
1094
+ if (externalSubjectId) try {
1095
+ const subject = await this.findSubjectByExternalId(externalSubjectId);
1096
+ if (subject) {
1097
+ ctx.logger?.debug('Found existing subject by external ID', {
1098
+ externalSubjectId
1099
+ });
1100
+ return subject;
1101
+ }
1102
+ ctx.logger?.info('Creating new subject with external ID', {
1103
+ externalSubjectId
1104
+ });
1105
+ return await this.createSubject({
1106
+ externalId: externalSubjectId,
1107
+ identityProvider: 'external',
1108
+ lastIpAddress: ipAddress,
1109
+ isIdentified: true
1110
+ }, context);
1111
+ } catch (error) {
1112
+ if (error instanceof Error && error.message.includes('unique constraint')) {
1113
+ ctx.logger?.info('Handling duplicate key violation for external ID', {
1114
+ externalSubjectId
1115
+ });
1116
+ const subject = await this.findSubjectByExternalId(externalSubjectId);
1117
+ if (subject) return subject;
1118
+ }
1119
+ ctx.logger?.error('Failed to create or find subject with external ID', {
1120
+ externalSubjectId,
1121
+ error: error instanceof Error ? error.message : 'Unknown error'
1122
+ });
1123
+ throw new error_class_DoubleTieError('Failed to create or find subject with external ID', {
1124
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1125
+ status: 500,
1126
+ meta: {
1127
+ error: error instanceof Error ? error.message : 'Unknown error'
1128
+ }
1129
+ });
1130
+ }
1131
+ try {
1132
+ ctx.logger?.info('Creating new anonymous subject');
1133
+ return await this.createSubject({
1134
+ externalId: null,
1135
+ identityProvider: 'anonymous',
1136
+ lastIpAddress: ipAddress,
1137
+ isIdentified: false
1138
+ }, context);
1139
+ } catch (error) {
1140
+ ctx.logger?.error('Failed to create anonymous subject', {
1141
+ ipAddress,
1142
+ error: error instanceof Error ? error.message : 'Unknown error'
1143
+ });
1144
+ throw new error_class_DoubleTieError('Failed to create anonymous subject', {
1145
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1146
+ status: 500,
1147
+ meta: {
1148
+ error: error instanceof Error ? error.message : 'Unknown error'
1149
+ }
1150
+ });
1151
+ }
1152
+ },
1153
+ findSubjectById: async (subjectId)=>{
1154
+ const subject = await adapter.findOne({
1155
+ model: 'subject',
1156
+ where: [
1157
+ {
1158
+ field: 'id',
1159
+ value: subjectId
1160
+ }
1161
+ ]
1162
+ });
1163
+ return subject ? validateEntityOutput('subject', subject, ctx.options) : null;
1164
+ },
1165
+ findSubjectByExternalId: async (externalId)=>{
1166
+ const subject = await adapter.findOne({
1167
+ model: 'subject',
1168
+ where: [
1169
+ {
1170
+ field: 'externalId',
1171
+ value: externalId
1172
+ }
1173
+ ]
1174
+ });
1175
+ return subject ? validateEntityOutput('subject', subject, ctx.options) : null;
1176
+ }
1177
+ };
1178
+ }
1179
+ function consentRegistry({ adapter, ...ctx }) {
1180
+ const { createWithHooks, updateWithHooks } = getWithHooks(adapter, ctx);
1181
+ const registry = {
1182
+ createConsent: async (consent, context)=>{
1183
+ const createdConsent = await createWithHooks({
1184
+ data: {
1185
+ createdAt: new Date(),
1186
+ ...consent
1187
+ },
1188
+ model: 'consent',
1189
+ context
1190
+ });
1191
+ if (!createdConsent) throw new error_class_DoubleTieError('Failed to create consent - operation returned null', {
1192
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1193
+ status: 500
1194
+ });
1195
+ return createdConsent;
1196
+ },
1197
+ updateConsent: async (consentId, data, context)=>{
1198
+ const consent = await updateWithHooks({
1199
+ data: {
1200
+ ...data
1201
+ },
1202
+ where: [
1203
+ {
1204
+ field: 'id',
1205
+ value: consentId
1206
+ }
1207
+ ],
1208
+ model: 'consent',
1209
+ context
1210
+ });
1211
+ return consent ? validateEntityOutput('consent', consent, ctx.options) : null;
1212
+ }
1213
+ };
1214
+ return registry;
1215
+ }
1216
+ const external_node_crypto_namespaceObject = require("node:crypto");
1217
+ function generatePolicyPlaceholder(name, date) {
1218
+ const content = `[PLACEHOLDER] This is an automatically generated version of the ${name} policy.\n\nThis placeholder content should be replaced with actual policy terms before being presented to users.\n\nGenerated on: ${date.toISOString()}`;
1219
+ const contentHash = (0, external_node_crypto_namespaceObject.createHash)('sha256').update(content).digest('hex');
1220
+ return {
1221
+ content,
1222
+ contentHash
1223
+ };
1224
+ }
1225
+ function policyRegistry({ adapter, ...ctx }) {
1226
+ const { createWithHooks } = getWithHooks(adapter, ctx);
1227
+ const registry = {
1228
+ createConsentPolicy: async (policy, context)=>{
1229
+ const createdPolicy = await createWithHooks({
1230
+ data: {
1231
+ createdAt: new Date(),
1232
+ ...policy
1233
+ },
1234
+ model: 'consentPolicy',
1235
+ context
1236
+ });
1237
+ if (!createdPolicy) throw new error_class_DoubleTieError('Failed to create consent policy - operation returned null', {
1238
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1239
+ status: 500
1240
+ });
1241
+ return createdPolicy;
1242
+ },
1243
+ findPolicies: async (params = {})=>{
1244
+ const whereConditions = [];
1245
+ if (!params.includeInactive) whereConditions.push({
1246
+ field: 'isActive',
1247
+ value: true
1248
+ });
1249
+ if (params.domainId) whereConditions.push({
1250
+ field: 'id',
1251
+ value: params.domainId
1252
+ });
1253
+ if (params.version) whereConditions.push({
1254
+ field: 'version',
1255
+ value: params.version
1256
+ });
1257
+ const policies = await adapter.findMany({
1258
+ model: 'consentPolicy',
1259
+ where: whereConditions,
1260
+ sortBy: {
1261
+ field: 'effectiveDate',
1262
+ direction: 'desc'
1263
+ }
1264
+ });
1265
+ return policies.map((policy)=>validateEntityOutput('consentPolicy', policy, ctx.options));
1266
+ },
1267
+ findConsentPolicyById: async (policyId)=>{
1268
+ const policy = await adapter.findOne({
1269
+ model: 'consentPolicy',
1270
+ where: [
1271
+ {
1272
+ field: 'id',
1273
+ value: policyId
1274
+ }
1275
+ ]
1276
+ });
1277
+ return policy ? validateEntityOutput('consentPolicy', policy, ctx.options) : null;
1278
+ },
1279
+ findOrCreatePolicy: async (type)=>adapter.transaction({
1280
+ callback: async (txAdapter)=>{
1281
+ const now = new Date();
1282
+ const txRegistry = policyRegistry({
1283
+ adapter: txAdapter,
1284
+ ...ctx
1285
+ });
1286
+ const rawLatestPolicy = await txAdapter.findOne({
1287
+ model: 'consentPolicy',
1288
+ where: [
1289
+ {
1290
+ field: 'isActive',
1291
+ value: true
1292
+ },
1293
+ {
1294
+ field: 'type',
1295
+ value: type
1296
+ }
1297
+ ],
1298
+ sortBy: {
1299
+ field: 'effectiveDate',
1300
+ direction: 'desc'
1301
+ }
1302
+ });
1303
+ const latestPolicy = rawLatestPolicy ? validateEntityOutput('consentPolicy', rawLatestPolicy, ctx.options) : null;
1304
+ if (latestPolicy) return latestPolicy;
1305
+ const { content: defaultContent, contentHash } = generatePolicyPlaceholder(type, now);
1306
+ return txRegistry.createConsentPolicy({
1307
+ version: '1.0.0',
1308
+ type,
1309
+ name: type,
1310
+ effectiveDate: now,
1311
+ content: defaultContent,
1312
+ contentHash,
1313
+ isActive: true,
1314
+ updatedAt: now,
1315
+ expirationDate: null
1316
+ });
1317
+ }
1318
+ })
1319
+ };
1320
+ return registry;
1321
+ }
1322
+ function consentPurposeRegistry({ adapter, ...ctx }) {
1323
+ const { createWithHooks } = getWithHooks(adapter, ctx);
1324
+ return {
1325
+ createConsentPurpose: async (consentPurpose, context)=>{
1326
+ const createdPurpose = await createWithHooks({
1327
+ data: {
1328
+ id: consentPurpose.id || '',
1329
+ createdAt: new Date(),
1330
+ updatedAt: new Date(),
1331
+ ...consentPurpose
1332
+ },
1333
+ model: 'consentPurpose',
1334
+ context
1335
+ });
1336
+ if (!createdPurpose) throw new error_class_DoubleTieError('Failed to create consent purpose - operation returned null', {
1337
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1338
+ status: 500
1339
+ });
1340
+ return validateEntityOutput('consentPurpose', createdPurpose, ctx.options);
1341
+ },
1342
+ findConsentPurposeByCode: async (code)=>{
1343
+ const consentPurpose = await adapter.findOne({
1344
+ model: 'consentPurpose',
1345
+ where: [
1346
+ {
1347
+ field: 'code',
1348
+ value: code
1349
+ }
1350
+ ]
1351
+ });
1352
+ return consentPurpose ? validateEntityOutput('consentPurpose', consentPurpose, ctx.options) : null;
1353
+ }
1354
+ };
1355
+ }
1356
+ function domainRegistry({ adapter, ...ctx }) {
1357
+ const { createWithHooks } = getWithHooks(adapter, ctx);
1358
+ const registry = {
1359
+ createDomain: async (domain, context)=>{
1360
+ const createdDomain = await createWithHooks({
1361
+ data: {
1362
+ ...domain,
1363
+ createdAt: new Date(),
1364
+ updatedAt: new Date()
1365
+ },
1366
+ model: 'domain',
1367
+ customFn: void 0,
1368
+ context
1369
+ });
1370
+ if (!createdDomain) throw new error_class_DoubleTieError('Failed to create domain - operation returned null', {
1371
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1372
+ status: 500
1373
+ });
1374
+ return createdDomain;
1375
+ },
1376
+ findOrCreateDomain: async function(name, context) {
1377
+ const existingDomain = await this.findDomainByName(name);
1378
+ if (existingDomain) return existingDomain;
1379
+ const domain = await this.createDomain({
1380
+ name,
1381
+ description: `Auto-created domain for ${name}`,
1382
+ isActive: true,
1383
+ isVerified: true,
1384
+ allowedOrigins: []
1385
+ }, context);
1386
+ if (!domain) throw new error_class_DoubleTieError('Failed to create domain', {
1387
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1388
+ status: 503
1389
+ });
1390
+ return domain;
1391
+ },
1392
+ findDomains: async (params = {})=>{
1393
+ const whereConditions = [];
1394
+ if (!params.includeInactive) whereConditions.push({
1395
+ field: 'isActive',
1396
+ value: true
1397
+ });
1398
+ if (params.name) whereConditions.push({
1399
+ field: 'name',
1400
+ value: params.name
1401
+ });
1402
+ const domains = await adapter.findMany({
1403
+ model: 'domain',
1404
+ where: whereConditions,
1405
+ sortBy: {
1406
+ field: 'name',
1407
+ direction: 'asc'
1408
+ }
1409
+ });
1410
+ return domains.map((domain)=>validateEntityOutput('domain', domain, ctx.options));
1411
+ },
1412
+ findDomain: async (name)=>{
1413
+ const domains = await registry.findDomains({
1414
+ name,
1415
+ includeInactive: false
1416
+ });
1417
+ return domains[0] || null;
1418
+ },
1419
+ findDomainByName: async (name)=>{
1420
+ const domain = await adapter.findOne({
1421
+ model: 'domain',
1422
+ where: [
1423
+ {
1424
+ field: 'name',
1425
+ value: name
1426
+ }
1427
+ ]
1428
+ });
1429
+ return domain ? validateEntityOutput('domain', domain, ctx.options) : null;
1430
+ }
1431
+ };
1432
+ return registry;
1433
+ }
1434
+ function auditLogRegistry({ adapter, ...ctx }) {
1435
+ const { createWithHooks } = getWithHooks(adapter, ctx);
1436
+ return {
1437
+ createAuditLog: async (auditLog, context)=>{
1438
+ const createdLog = await createWithHooks({
1439
+ data: {
1440
+ createdAt: new Date(),
1441
+ ...auditLog
1442
+ },
1443
+ model: 'auditLog',
1444
+ customFn: void 0,
1445
+ context
1446
+ });
1447
+ if (!createdLog) throw new error_class_DoubleTieError('Failed to create audit log - operation returned null', {
1448
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
1449
+ status: 500
1450
+ });
1451
+ return createdLog;
1452
+ }
1453
+ };
1454
+ }
1455
+ async function processHooks(data, model, operation, phase, hooks, context) {
1456
+ let currentData = {
1457
+ ...data
1458
+ };
1459
+ for (const hookSet of hooks){
1460
+ const modelHooks = hookSet[model];
1461
+ if (!modelHooks) continue;
1462
+ const operationHooks = modelHooks[operation];
1463
+ if (!operationHooks) continue;
1464
+ const hookFn = operationHooks[phase];
1465
+ if (hookFn) if ('before' === phase) {
1466
+ const result = await hookFn(currentData, context);
1467
+ if (result && 'object' == typeof result && 'kind' in result) switch(result.kind){
1468
+ case 'abort':
1469
+ return null;
1470
+ case 'transform':
1471
+ {
1472
+ const transformData = result.data;
1473
+ currentData = {
1474
+ ...currentData,
1475
+ ...transformData
1476
+ };
1477
+ break;
1478
+ }
1479
+ default:
1480
+ break;
1481
+ }
1482
+ } else await hookFn(currentData, context);
1483
+ }
1484
+ return currentData;
1485
+ }
1486
+ async function processAfterHooksForMany(records, model, hooks, context) {
1487
+ if (!records.length) return;
1488
+ for (const record of records)await processHooks(record, model, 'update', 'after', hooks, context);
1489
+ }
1490
+ async function create_hooks_createWithHooks(adapter, ctx, props) {
1491
+ const { data, model, customFn, context } = props;
1492
+ const hooks = ctx.hooks || [];
1493
+ const transformedData = await processHooks(data, model, 'create', 'before', hooks, context);
1494
+ if (null === transformedData) return null;
1495
+ let created = null;
1496
+ if (customFn) {
1497
+ created = await customFn.fn(transformedData);
1498
+ if (!customFn.executeMainFn && created) return created;
1499
+ }
1500
+ if (!created) created = await adapter.create({
1501
+ model: model,
1502
+ data: transformedData
1503
+ });
1504
+ if (created) await processHooks(created, model, 'create', 'after', hooks, context);
1505
+ return created;
1506
+ }
1507
+ async function update_hooks_updateWithHooks(adapter, ctx, props) {
1508
+ const { data, where, model, customFn, context } = props;
1509
+ const hooks = ctx.hooks || [];
1510
+ const transformedData = await processHooks(data, model, 'update', 'before', hooks, context);
1511
+ if (null === transformedData) return null;
1512
+ let updated = null;
1513
+ if (customFn) {
1514
+ const result = await customFn.fn(transformedData);
1515
+ updated = result;
1516
+ if (!customFn.executeMainFn && updated) return updated;
1517
+ }
1518
+ if (!updated) updated = await adapter.update({
1519
+ model: model,
1520
+ update: transformedData,
1521
+ where
1522
+ });
1523
+ if (updated) await processHooks(updated, model, 'update', 'after', hooks, context);
1524
+ return updated;
1525
+ }
1526
+ async function executeCustomFunction(data, customFn) {
1527
+ if (!customFn) return {
1528
+ result: null,
1529
+ shouldContinue: true
1530
+ };
1531
+ const result = await customFn.fn(data);
1532
+ const shouldContinue = !result || !!customFn.executeMainFn;
1533
+ return {
1534
+ result,
1535
+ shouldContinue
1536
+ };
1537
+ }
1538
+ function processUpdateManyResult(result) {
1539
+ if (Array.isArray(result)) return result;
1540
+ if ('number' == typeof result && result > 0) return [];
1541
+ return null;
1542
+ }
1543
+ async function updateManyWithHooks(adapter, ctx, props) {
1544
+ const { data, where, model, customFn, context } = props;
1545
+ const hooks = ctx.hooks || [];
1546
+ const transformedData = await processHooks(data, model, 'update', 'before', hooks, context);
1547
+ if (null === transformedData) return null;
1548
+ const { result: customResult, shouldContinue } = await executeCustomFunction(transformedData, customFn);
1549
+ if (customResult && !shouldContinue) return customResult;
1550
+ let updated = customResult;
1551
+ if (!updated) {
1552
+ const adapterResult = await adapter.updateMany({
1553
+ model: model,
1554
+ update: transformedData,
1555
+ where
1556
+ });
1557
+ updated = processUpdateManyResult(adapterResult);
1558
+ }
1559
+ if (updated && updated.length > 0) await processAfterHooksForMany(updated, model, hooks, context);
1560
+ return updated;
1561
+ }
1562
+ function getWithHooks(adapter, ctx) {
1563
+ return {
1564
+ createWithHooks: ({ data, model, customFn, context })=>create_hooks_createWithHooks(adapter, ctx, {
1565
+ data,
1566
+ model,
1567
+ customFn,
1568
+ context
1569
+ }),
1570
+ updateWithHooks: (props)=>update_hooks_updateWithHooks(adapter, ctx, props),
1571
+ updateManyWithHooks: (props)=>updateManyWithHooks(adapter, ctx, props)
1572
+ };
1573
+ }
1574
+ const createEntityTransformer = (db, options, config)=>{
1575
+ const schema = definition_getConsentTables(options);
1576
+ function getField(model, field) {
1577
+ if ('id' === field) return field;
1578
+ const modelFields = schema[model]?.fields;
1579
+ const f = modelFields ? modelFields[field] : void 0;
1580
+ if (!f) console.log('Field not found', model, field);
1581
+ return f?.fieldName || field;
1582
+ }
1583
+ function transformValueToDB(value, model, field) {
1584
+ if ('id' === field) return value;
1585
+ const { type = 'sqlite' } = config || {};
1586
+ const modelFields = schema[model]?.fields;
1587
+ const f = modelFields ? modelFields[field] : void 0;
1588
+ if (f?.type === 'boolean' && ('sqlite' === type || 'mssql' === type) && null != value) return value ? 1 : 0;
1589
+ if (f?.type === 'date' && value && value instanceof Date) return 'sqlite' === type ? value.toISOString() : value;
1590
+ if (f?.type === 'json' && null != value) {
1591
+ if ('postgres' === type || 'mysql' === type) return value;
1592
+ return external_superjson_default().stringify(value);
1593
+ }
1594
+ return value;
1595
+ }
1596
+ function transformValueFromDB(value, model, field) {
1597
+ const { type = 'sqlite' } = config || {};
1598
+ const modelFields = schema[model]?.fields;
1599
+ const f = modelFields ? modelFields[field] : void 0;
1600
+ if (f?.type === 'boolean' && ('sqlite' === type || 'mssql' === type) && null !== value) return 1 === value;
1601
+ if (f?.type === 'date' && value) return new Date(value);
1602
+ if (f?.type === 'json' && null != value) {
1603
+ if (('postgres' === type || 'mysql' === type) && 'object' == typeof value) return value;
1604
+ if ('string' == typeof value) try {
1605
+ return external_superjson_default().parse(value);
1606
+ } catch {
1607
+ try {
1608
+ return JSON.parse(value);
1609
+ } catch {}
1610
+ }
1611
+ }
1612
+ return value;
1613
+ }
1614
+ function getEntityName(model) {
1615
+ return schema[model].entityName;
1616
+ }
1617
+ return {
1618
+ transformInput (data, model, action) {
1619
+ const transformedData = {};
1620
+ if ('create' === action) {
1621
+ const advancedOptions = options.advanced || {};
1622
+ transformedData.id = data.id || (advancedOptions.generateId ? advancedOptions.generateId({
1623
+ model
1624
+ }) : id_generator_generateId(schema[model].entityPrefix));
1625
+ }
1626
+ const fields = schema[model].fields;
1627
+ for(const field in fields)if (Object.hasOwn(fields, field)) {
1628
+ const value = data[field];
1629
+ const fieldInfo = fields[field];
1630
+ const fieldName = fieldInfo?.fieldName || field;
1631
+ if (fieldInfo) transformedData[fieldName] = utils_applyDefaultValue(transformValueToDB(value, model, field), fieldInfo, action);
1632
+ }
1633
+ return transformedData;
1634
+ },
1635
+ transformOutput (data, model, select = []) {
1636
+ if (!data) return null;
1637
+ const transformedData = {};
1638
+ if (data.id && (0 === select.length || select.includes('id'))) transformedData.id = data.id;
1639
+ const tableSchema = schema[model]?.fields;
1640
+ for(const key in tableSchema){
1641
+ if (select.length && !select.includes(key)) continue;
1642
+ const field = tableSchema[key];
1643
+ if (field) transformedData[key] = transformValueFromDB(data[field.fieldName || key], model, key);
1644
+ }
1645
+ return transformedData;
1646
+ },
1647
+ convertWhereClause (model, whereConditions) {
1648
+ if (!whereConditions || 0 === whereConditions.length) return {
1649
+ and: null,
1650
+ or: null
1651
+ };
1652
+ const conditions = {
1653
+ and: [],
1654
+ or: []
1655
+ };
1656
+ for (const condition of whereConditions){
1657
+ let { field: _field, value, operator = '=', connector = 'AND' } = condition;
1658
+ const fieldString = getField(model, _field);
1659
+ value = transformValueToDB(value, model, _field);
1660
+ const expr = (eb)=>{
1661
+ const dbField = fieldString;
1662
+ if ('in' === operator.toLowerCase()) return eb(dbField, 'in', Array.isArray(value) ? value : [
1663
+ value
1664
+ ]);
1665
+ if ('contains' === operator) return eb(dbField, 'like', `%${value}%`);
1666
+ if ('starts_with' === operator) return eb(dbField, 'like', `${value}%`);
1667
+ if ('ends_with' === operator) return eb(dbField, 'like', `%${value}`);
1668
+ if ('ilike' === operator) {
1669
+ const lowerField = eb.fn('lower', [
1670
+ dbField
1671
+ ]);
1672
+ const lowerValue = eb.fn('lower', [
1673
+ eb.val(value?.toString())
1674
+ ]);
1675
+ return eb(lowerField, 'like', lowerValue);
1676
+ }
1677
+ if ('eq' === operator) return eb(dbField, '=', value);
1678
+ if ('ne' === operator) return eb(dbField, '<>', value);
1679
+ if ('gt' === operator) return eb(dbField, '>', value);
1680
+ if ('gte' === operator) return eb(dbField, '>=', value);
1681
+ if ('lt' === operator) return eb(dbField, '<', value);
1682
+ if ('lte' === operator) return eb(dbField, '<=', value);
1683
+ return eb(dbField, operator, value);
1684
+ };
1685
+ if ('OR' === connector) conditions.or.push(expr);
1686
+ else conditions.and.push(expr);
1687
+ }
1688
+ return {
1689
+ and: conditions.and.length ? conditions.and : null,
1690
+ or: conditions.or.length ? conditions.or : null
1691
+ };
1692
+ },
1693
+ async withReturning (values, builder, model, where) {
1694
+ let res = null;
1695
+ if (config?.type === 'mysql') {
1696
+ await builder.execute();
1697
+ const whereCondition = where[0];
1698
+ const field = values.id ? 'id' : whereCondition?.field ?? 'id';
1699
+ const value = values[field] ?? whereCondition?.value;
1700
+ const fieldString = getField(model, field);
1701
+ res = await db.selectFrom(getEntityName(model)).selectAll().where((eb)=>eb(fieldString, '=', value)).executeTakeFirst();
1702
+ return res;
1703
+ }
1704
+ if (config?.type === 'mssql') {
1705
+ res = await builder.outputAll('inserted').executeTakeFirst();
1706
+ return res;
1707
+ }
1708
+ res = await builder.returningAll().executeTakeFirst();
1709
+ return res;
1710
+ },
1711
+ getEntityName,
1712
+ getField
1713
+ };
1714
+ };
1715
+ const kyselyAdapter = (db, config)=>(opts)=>{
1716
+ const { transformInput, withReturning, transformOutput, convertWhereClause, getEntityName, getField } = createEntityTransformer(db, opts, config);
1717
+ return {
1718
+ id: 'kysely',
1719
+ async create (data) {
1720
+ const { model, data: values, select } = data;
1721
+ const transformed = transformInput(values, model, 'create');
1722
+ const tableName = getEntityName(model);
1723
+ const builder = db.insertInto(tableName).values(transformed);
1724
+ const result = await withReturning(transformed, builder, model, []);
1725
+ const output = transformOutput(result, model, select);
1726
+ return output;
1727
+ },
1728
+ async findOne (data) {
1729
+ const { model, where, select } = data;
1730
+ const whereArray = Array.isArray(where) ? where : [
1731
+ where
1732
+ ];
1733
+ const { and, or } = convertWhereClause(model, whereArray);
1734
+ const tableName = getEntityName(model);
1735
+ let query = db.selectFrom(tableName).selectAll();
1736
+ if (and) query = query.where((eb)=>{
1737
+ const conditions = and.map((expr)=>expr(eb));
1738
+ return eb.and(conditions);
1739
+ });
1740
+ if (or) query = query.where((eb)=>{
1741
+ const conditions = or.map((expr)=>expr(eb));
1742
+ return eb.or(conditions);
1743
+ });
1744
+ const res = await query.executeTakeFirst();
1745
+ if (!res) return null;
1746
+ return transformOutput(res, model, select);
1747
+ },
1748
+ async findMany (data) {
1749
+ const { model, where, limit, offset, sortBy } = data;
1750
+ const whereArray = where ? Array.isArray(where) ? where : [
1751
+ where
1752
+ ] : void 0;
1753
+ const { and, or } = convertWhereClause(model, whereArray);
1754
+ const tableName = getEntityName(model);
1755
+ let query = db.selectFrom(tableName);
1756
+ if (and) query = query.where((eb)=>{
1757
+ const conditions = and.map((expr)=>expr(eb));
1758
+ return eb.and(conditions);
1759
+ });
1760
+ if (or) query = query.where((eb)=>{
1761
+ const conditions = or.map((expr)=>expr(eb));
1762
+ return eb.or(conditions);
1763
+ });
1764
+ if (config?.type === 'mssql') {
1765
+ if (!offset) query = query.top(limit || 100);
1766
+ } else query = query.limit(limit || 100);
1767
+ if (sortBy) {
1768
+ const sortFieldString = getField(model, sortBy.field);
1769
+ query = query.orderBy(sortFieldString, sortBy.direction);
1770
+ }
1771
+ if (offset) if (config?.type === 'mssql') {
1772
+ if (!sortBy) query = query.orderBy('id');
1773
+ query = query.offset(offset).fetch(limit || 100);
1774
+ } else query = query.offset(offset);
1775
+ const res = await query.selectAll().execute();
1776
+ if (!res) return [];
1777
+ return res.map((r)=>transformOutput(r, model));
1778
+ },
1779
+ async update (data) {
1780
+ const { model, where, update: values } = data;
1781
+ const whereArray = Array.isArray(where) ? where : [
1782
+ where
1783
+ ];
1784
+ const { and, or } = convertWhereClause(model, whereArray);
1785
+ const transformedData = transformInput(values, model, 'update');
1786
+ const tableName = getEntityName(model);
1787
+ let query = db.updateTable(tableName).set(transformedData);
1788
+ if (and) query = query.where((eb)=>{
1789
+ const conditions = and.map((expr)=>expr(eb));
1790
+ return eb.and(conditions);
1791
+ });
1792
+ if (or) query = query.where((eb)=>{
1793
+ const conditions = or.map((expr)=>expr(eb));
1794
+ return eb.or(conditions);
1795
+ });
1796
+ const result = await withReturning(transformedData, query, model, whereArray);
1797
+ return transformOutput(result, model);
1798
+ },
1799
+ async updateMany (data) {
1800
+ const { model, where, update: values } = data;
1801
+ const whereArray = Array.isArray(where) ? where : [
1802
+ where
1803
+ ];
1804
+ const { and, or } = convertWhereClause(model, whereArray);
1805
+ const transformedData = transformInput(values, model, 'update');
1806
+ const tableName = getEntityName(model);
1807
+ let query = db.updateTable(tableName).set(transformedData);
1808
+ if (and) query = query.where((eb)=>{
1809
+ const conditions = and.map((expr)=>expr(eb));
1810
+ return eb.and(conditions);
1811
+ });
1812
+ if (or) query = query.where((eb)=>{
1813
+ const conditions = or.map((expr)=>expr(eb));
1814
+ return eb.or(conditions);
1815
+ });
1816
+ await query.execute();
1817
+ let selectQuery = db.selectFrom(tableName).selectAll();
1818
+ if (and) selectQuery = selectQuery.where((eb)=>{
1819
+ const conditions = and.map((expr)=>expr(eb));
1820
+ return eb.and(conditions);
1821
+ });
1822
+ if (or) selectQuery = selectQuery.where((eb)=>{
1823
+ const conditions = or.map((expr)=>expr(eb));
1824
+ return eb.or(conditions);
1825
+ });
1826
+ const fetchedResults = await selectQuery.execute();
1827
+ if (!fetchedResults || 0 === fetchedResults.length) return [];
1828
+ return fetchedResults.map((record)=>transformOutput(record, model));
1829
+ },
1830
+ async count (data) {
1831
+ const { model, where } = data;
1832
+ const whereArray = where ? Array.isArray(where) ? where : [
1833
+ where
1834
+ ] : void 0;
1835
+ const { and, or } = convertWhereClause(model, whereArray);
1836
+ const tableName = getEntityName(model);
1837
+ let query = db.selectFrom(tableName).select((eb)=>eb.fn.count('id').as('count'));
1838
+ if (and) query = query.where((eb)=>{
1839
+ const conditions = and.map((expr)=>expr(eb));
1840
+ return eb.and(conditions);
1841
+ });
1842
+ if (or) query = query.where((eb)=>{
1843
+ const conditions = or.map((expr)=>expr(eb));
1844
+ return eb.or(conditions);
1845
+ });
1846
+ const res = await query.execute();
1847
+ const count = res[0]?.count;
1848
+ return 'number' == typeof count ? count : 0;
1849
+ },
1850
+ async delete (data) {
1851
+ const { model, where } = data;
1852
+ const whereArray = Array.isArray(where) ? where : [
1853
+ where
1854
+ ];
1855
+ const { and, or } = convertWhereClause(model, whereArray);
1856
+ const tableName = getEntityName(model);
1857
+ let query = db.deleteFrom(tableName);
1858
+ if (and) query = query.where((eb)=>{
1859
+ const conditions = and.map((expr)=>expr(eb));
1860
+ return eb.and(conditions);
1861
+ });
1862
+ if (or) query = query.where((eb)=>{
1863
+ const conditions = or.map((expr)=>expr(eb));
1864
+ return eb.or(conditions);
1865
+ });
1866
+ await query.execute();
1867
+ },
1868
+ async deleteMany (data) {
1869
+ const { model, where } = data;
1870
+ const whereArray = Array.isArray(where) ? where : [
1871
+ where
1872
+ ];
1873
+ const { and, or } = convertWhereClause(model, whereArray);
1874
+ const tableName = getEntityName(model);
1875
+ let query = db.deleteFrom(tableName);
1876
+ if (and) query = query.where((eb)=>{
1877
+ const conditions = and.map((expr)=>expr(eb));
1878
+ return eb.and(conditions);
1879
+ });
1880
+ if (or) query = query.where((eb)=>{
1881
+ const conditions = or.map((expr)=>expr(eb));
1882
+ return eb.or(conditions);
1883
+ });
1884
+ const result = await query.execute();
1885
+ const count = result.length;
1886
+ return count;
1887
+ },
1888
+ async transaction (data) {
1889
+ const { callback } = data;
1890
+ const advancedOptions = opts.advanced || {};
1891
+ if (advancedOptions.disableTransactions) {
1892
+ const regularAdapter = kyselyAdapter(db, config)(opts);
1893
+ return await callback(regularAdapter);
1894
+ }
1895
+ try {
1896
+ return await db.transaction().execute(async (trx)=>{
1897
+ const transactionAdapter = kyselyAdapter(trx, config)(opts);
1898
+ return await callback(transactionAdapter);
1899
+ });
1900
+ } catch (error) {
1901
+ if (error instanceof Error && (error.message.includes('transactions are not supported') || error.message.toLowerCase().includes('no transaction support'))) {
1902
+ console.warn("Warning: Database transaction failed. If your database does not support transactions, you can disable this warning by setting opts.advanced.disableTransactions to true.");
1903
+ const regularAdapter = kyselyAdapter(db, config)(opts);
1904
+ return await callback(regularAdapter);
1905
+ }
1906
+ throw error;
1907
+ }
1908
+ },
1909
+ options: config
1910
+ };
1911
+ };
1912
+ const external_kysely_namespaceObject = require("kysely");
1913
+ function getDatabaseType(db) {
1914
+ if (!db) return null;
1915
+ if ('dialect' in db) return getDatabaseType(db.dialect);
1916
+ if (db && 'object' == typeof db && 'createDriver' in db) {
1917
+ if (db instanceof external_kysely_namespaceObject.SqliteDialect) return 'sqlite';
1918
+ if (db instanceof external_kysely_namespaceObject.MysqlDialect) return 'mysql';
1919
+ if (db instanceof external_kysely_namespaceObject.PostgresDialect) return 'postgres';
1920
+ if (db instanceof external_kysely_namespaceObject.MssqlDialect) return 'mssql';
1921
+ }
1922
+ if (db && 'object' == typeof db && 'aggregate' in db) return 'sqlite';
1923
+ if (db && 'object' == typeof db && 'getConnection' in db) return 'mysql';
1924
+ if (db && 'object' == typeof db && 'connect' in db) return 'postgres';
1925
+ return null;
1926
+ }
1927
+ const createKyselyAdapter = async (config)=>{
1928
+ const db = config.database;
1929
+ if (!db) return {
1930
+ kysely: null,
1931
+ databaseType: null
1932
+ };
1933
+ if (db && 'object' == typeof db && 'db' in db) {
1934
+ const kyselyConfig = db;
1935
+ return {
1936
+ kysely: kyselyConfig.db,
1937
+ databaseType: kyselyConfig.type
1938
+ };
1939
+ }
1940
+ if (db && 'object' == typeof db && 'dialect' in db) {
1941
+ const dialectConfig = db;
1942
+ return {
1943
+ kysely: new external_kysely_namespaceObject.Kysely({
1944
+ dialect: dialectConfig.dialect
1945
+ }),
1946
+ databaseType: dialectConfig.type
1947
+ };
1948
+ }
1949
+ let dialect;
1950
+ const databaseType = getDatabaseType(db);
1951
+ if (db && 'object' == typeof db && 'createDriver' in db) dialect = db;
1952
+ if (db && 'object' == typeof db && 'aggregate' in db) dialect = new external_kysely_namespaceObject.SqliteDialect({
1953
+ database: db
1954
+ });
1955
+ if (db && 'object' == typeof db && 'getConnection' in db) dialect = new external_kysely_namespaceObject.MysqlDialect({
1956
+ pool: db
1957
+ });
1958
+ if (db && 'object' == typeof db && 'connect' in db) dialect = new external_kysely_namespaceObject.PostgresDialect({
1959
+ pool: db
1960
+ });
1961
+ return {
1962
+ kysely: dialect ? new external_kysely_namespaceObject.Kysely({
1963
+ dialect
1964
+ }) : null,
1965
+ databaseType
1966
+ };
1967
+ };
1968
+ const memory_adapter_createEntityTransformer = (options)=>{
1969
+ const schema = definition_getConsentTables(options);
1970
+ function getField(model, field) {
1971
+ if ('id' === field) return field;
1972
+ const modelFields = schema[model]?.fields;
1973
+ const f = modelFields ? modelFields[field] : void 0;
1974
+ return f?.fieldName || field;
1975
+ }
1976
+ return {
1977
+ transformInput (data, model, action) {
1978
+ const advancedOptions = options.advanced || {};
1979
+ const transformedData = 'update' === action ? {} : {
1980
+ id: advancedOptions.generateId ? advancedOptions.generateId({
1981
+ model
1982
+ }) : data.id || id_generator_generateId(schema[model].entityPrefix)
1983
+ };
1984
+ const fields = schema[model].fields;
1985
+ for(const field in fields)if (Object.hasOwn(fields, field)) {
1986
+ const value = data[field];
1987
+ const fieldInfo = fields[field];
1988
+ if (void 0 === value && !fieldInfo?.defaultValue) continue;
1989
+ const fieldName = fieldInfo?.fieldName || field;
1990
+ transformedData[fieldName] = utils_applyDefaultValue(value, fieldInfo, action);
1991
+ }
1992
+ return transformedData;
1993
+ },
1994
+ transformOutput (data, model, select = []) {
1995
+ if (!data) return null;
1996
+ const transformedData = {};
1997
+ const hasId = data.id || data._id;
1998
+ if (hasId && (0 === select.length || select.includes('id'))) transformedData.id = data.id;
1999
+ const tableSchema = schema[model].fields;
2000
+ for(const key in tableSchema){
2001
+ if (select.length && !select.includes(key)) continue;
2002
+ const field = tableSchema[key];
2003
+ if (field) transformedData[key] = data[field.fieldName || key];
2004
+ }
2005
+ return transformedData;
2006
+ },
2007
+ convertWhereClause (where, table, model) {
2008
+ return table.filter((record)=>where.every((clause)=>{
2009
+ const { field: _field, value, operator = '=' } = clause;
2010
+ const field = getField(model, _field);
2011
+ if ('in' === operator) {
2012
+ if (!Array.isArray(value)) throw new Error('Value must be an array');
2013
+ return value.includes(record[field]);
2014
+ }
2015
+ if ('contains' === operator) {
2016
+ const fieldValue = record[field];
2017
+ return 'string' == typeof fieldValue && fieldValue.includes(value);
2018
+ }
2019
+ if ('starts_with' === operator) {
2020
+ const fieldValue = record[field];
2021
+ return 'string' == typeof fieldValue && fieldValue.startsWith(value);
2022
+ }
2023
+ if ('ends_with' === operator) {
2024
+ const fieldValue = record[field];
2025
+ return 'string' == typeof fieldValue && fieldValue.endsWith(value);
2026
+ }
2027
+ if ('eq' === operator) return record[field] === value;
2028
+ if ('ne' === operator) return record[field] !== value;
2029
+ return record[field] === value;
2030
+ }));
2031
+ },
2032
+ getField
2033
+ };
2034
+ };
2035
+ const memoryAdapter = (db)=>(options)=>{
2036
+ const { transformInput, transformOutput, convertWhereClause, getField } = memory_adapter_createEntityTransformer(options);
2037
+ const schema = definition_getConsentTables(options);
2038
+ for(const model in schema)if (!db[model]) db[model] = [];
2039
+ return {
2040
+ id: 'memory',
2041
+ async create (data) {
2042
+ const { model, data: values, select } = data;
2043
+ const transformed = transformInput(values, model, 'create');
2044
+ if (!db[model]) db[model] = [];
2045
+ db[model].push(transformed);
2046
+ return transformOutput(transformed, model, select);
2047
+ },
2048
+ async findOne (data) {
2049
+ const { model, where, select } = data;
2050
+ const table = db[model] || [];
2051
+ const whereArray = Array.isArray(where) ? where : [
2052
+ where
2053
+ ];
2054
+ const res = convertWhereClause(whereArray, table, model);
2055
+ const record = res[0] || null;
2056
+ return transformOutput(record, model, select);
2057
+ },
2058
+ async findMany (data) {
2059
+ const { model, where, sortBy, limit, offset } = data;
2060
+ let table = db[model] || [];
2061
+ if (where) {
2062
+ const whereArray = Array.isArray(where) ? where : [
2063
+ where
2064
+ ];
2065
+ table = convertWhereClause(whereArray, table, model);
2066
+ }
2067
+ if (sortBy) {
2068
+ const field = getField(model, sortBy.field);
2069
+ table = [
2070
+ ...table
2071
+ ].sort((a, b)=>{
2072
+ if ('asc' === sortBy.direction) return a[field] > b[field] ? 1 : -1;
2073
+ return a[field] < b[field] ? 1 : -1;
2074
+ });
2075
+ }
2076
+ let result = table;
2077
+ if (void 0 !== offset) result = result.slice(offset);
2078
+ if (void 0 !== limit) result = result.slice(0, limit);
2079
+ return result.map((record)=>transformOutput(record, model));
2080
+ },
2081
+ async count (data) {
2082
+ const { model, where } = data;
2083
+ const table = db[model] || [];
2084
+ if (!where) return table.length;
2085
+ const whereArray = Array.isArray(where) ? where : [
2086
+ where
2087
+ ];
2088
+ const filtered = convertWhereClause(whereArray, table, model);
2089
+ return filtered.length;
2090
+ },
2091
+ async update (data) {
2092
+ const { model, where, update: values } = data;
2093
+ const table = db[model] || [];
2094
+ const whereArray = Array.isArray(where) ? where : [
2095
+ where
2096
+ ];
2097
+ const res = convertWhereClause(whereArray, table, model);
2098
+ for (const record of res)Object.assign(record, transformInput(values, model, 'update'));
2099
+ return transformOutput(res[0] || null, model);
2100
+ },
2101
+ async updateMany (data) {
2102
+ const { model, where, update: values } = data;
2103
+ const table = db[model] || [];
2104
+ const whereArray = Array.isArray(where) ? where : [
2105
+ where
2106
+ ];
2107
+ const res = convertWhereClause(whereArray, table, model);
2108
+ for (const record of res)Object.assign(record, transformInput(values, model, 'update'));
2109
+ return res.map((record)=>transformOutput(record, model));
2110
+ },
2111
+ async delete (data) {
2112
+ const { model, where } = data;
2113
+ const table = db[model] || [];
2114
+ const whereArray = Array.isArray(where) ? where : [
2115
+ where
2116
+ ];
2117
+ const res = convertWhereClause(whereArray, table, model);
2118
+ db[model] = table.filter((record)=>!res.includes(record));
2119
+ },
2120
+ async deleteMany (data) {
2121
+ const { model, where } = data;
2122
+ const table = db[model] || [];
2123
+ const whereArray = Array.isArray(where) ? where : [
2124
+ where
2125
+ ];
2126
+ const res = convertWhereClause(whereArray, table, model);
2127
+ let count = 0;
2128
+ db[model] = table.filter((record)=>{
2129
+ if (res.includes(record)) {
2130
+ count++;
2131
+ return false;
2132
+ }
2133
+ return true;
2134
+ });
2135
+ return count;
2136
+ },
2137
+ async transaction (data) {
2138
+ const { callback } = data;
2139
+ const tempDb = {};
2140
+ for(const key in db)if (Object.hasOwn(db, key)) tempDb[key] = JSON.parse(JSON.stringify(db[key]));
2141
+ const transactionAdapter = memoryAdapter(tempDb)(options);
2142
+ const result = await callback(transactionAdapter);
2143
+ for(const key in tempDb)if (Object.hasOwn(tempDb, key)) db[key] = tempDb[key];
2144
+ return result;
2145
+ }
2146
+ };
2147
+ };
2148
+ require("drizzle-orm");
2149
+ let globalLogger;
2150
+ function getLogger(options) {
2151
+ if (!globalLogger) globalLogger = (0, logger_namespaceObject.createLogger)({
2152
+ level: 'info',
2153
+ appName: 'c15t',
2154
+ ...options
2155
+ });
2156
+ return globalLogger;
2157
+ }
2158
+ function initLogger(options) {
2159
+ globalLogger = (0, logger_namespaceObject.createLogger)(options);
2160
+ return globalLogger;
2161
+ }
2162
+ async function getAdapter(options) {
2163
+ const logger = getLogger({
2164
+ appName: options.appName ?? 'c15t',
2165
+ ...options.logger
2166
+ });
2167
+ if (!options.database) {
2168
+ const tables = definition_getConsentTables(options);
2169
+ const memoryDB = Object.keys(tables).reduce((acc, key)=>{
2170
+ acc[key] = [];
2171
+ return acc;
2172
+ }, {});
2173
+ logger.warn('No database configuration provided. Using memory adapter in development');
2174
+ return memoryAdapter(memoryDB)(options);
2175
+ }
2176
+ if ('function' == typeof options.database) return options.database(options);
2177
+ const { kysely, databaseType } = await createKyselyAdapter(options);
2178
+ if (!kysely) throw new error_class_DoubleTieError('Failed to initialize database adapter', {
2179
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
2180
+ status: 500
2181
+ });
2182
+ return kyselyAdapter(kysely, {
2183
+ type: databaseType || 'sqlite'
2184
+ })(options);
2185
+ }
2186
+ const env = 'undefined' != typeof process ? process.env : {};
2187
+ 'undefined' != typeof process && process.env.NODE_ENV;
2188
+ function toBoolean(val) {
2189
+ return val ? 'false' !== val : false;
2190
+ }
2191
+ const nodeENV = 'undefined' != typeof process && process.env && process.env.NODE_ENV || '';
2192
+ const isTest = 'test' === nodeENV || toBoolean(env.TEST);
2193
+ const TRAILING_SLASHES_REGEX = /\/+$/;
2194
+ function checkHasPath(url) {
2195
+ try {
2196
+ const parsedUrl = new URL(url);
2197
+ return '/' !== parsedUrl.pathname;
2198
+ } catch {
2199
+ throw new error_class_DoubleTieError(`Invalid base URL: ${url}. Please provide a valid base URL.`, {
2200
+ code: error_codes_ERROR_CODES.BAD_REQUEST,
2201
+ status: 400,
2202
+ meta: {
2203
+ url
2204
+ }
2205
+ });
2206
+ }
2207
+ }
2208
+ function withPath(url, path = '/api/auth') {
2209
+ const hasPath = checkHasPath(url);
2210
+ if (hasPath) return url;
2211
+ const pathWithSlash = path.startsWith('/') ? path : `/${path}`;
2212
+ return `${url.replace(TRAILING_SLASHES_REGEX, '')}${pathWithSlash}`;
2213
+ }
2214
+ function getBaseURL(url, path) {
2215
+ if (url) return withPath(url, path);
2216
+ const fromEnv = env.C15T_URL || env.NEXT_PUBLIC_C15T_URL || env.PUBLIC_C15T_URL || env.NUXT_PUBLIC_C15T_URL || env.NUXT_PUBLIC_AUTH_URL || ('/' !== env.BASE_URL ? env.BASE_URL : void 0);
2217
+ if (fromEnv) return withPath(fromEnv, path);
2218
+ }
2219
+ const createRegistry = (ctx)=>({
2220
+ ...auditLogRegistry(ctx),
2221
+ ...consentRegistry(ctx),
2222
+ ...domainRegistry(ctx),
2223
+ ...consentPurposeRegistry(ctx),
2224
+ ...policyRegistry(ctx),
2225
+ ...subjectRegistry(ctx)
2226
+ });
2227
+ let telemetrySdk;
2228
+ const init = async (options)=>{
2229
+ try {
2230
+ const loggerOptions = options.logger;
2231
+ const baseUrlStr = options.baseURL;
2232
+ const basePathStr = options.basePath;
2233
+ const databaseHooks = options.databaseHooks || [];
2234
+ const appName = options.appName || 'c15t';
2235
+ const logger = initLogger({
2236
+ ...loggerOptions,
2237
+ appName: String(appName)
2238
+ });
2239
+ const telemetryOptions = createTelemetryOptions(String(appName), options.telemetry);
2240
+ let telemetryInitialized = false;
2241
+ try {
2242
+ if (telemetrySdk) {
2243
+ logger.debug('Telemetry SDK already initialized, skipping');
2244
+ telemetryInitialized = true;
2245
+ } else if (telemetryOptions?.disabled) {
2246
+ logger.info('Telemetry is disabled by configuration');
2247
+ telemetryInitialized = false;
2248
+ } else {
2249
+ const resource = new resources_namespaceObject.Resource({
2250
+ 'service.name': String(appName),
2251
+ 'service.version': String(package_namespaceObject.i8 || '1.0.0'),
2252
+ ...telemetryOptions?.defaultAttributes || {}
2253
+ });
2254
+ logger.debug('Initializing telemetry with resource attributes', {
2255
+ attributes: resource.attributes
2256
+ });
2257
+ const traceExporter = telemetryOptions?.tracer ? void 0 : new sdk_trace_base_namespaceObject.ConsoleSpanExporter();
2258
+ telemetrySdk = new sdk_node_namespaceObject.NodeSDK({
2259
+ resource,
2260
+ traceExporter
2261
+ });
2262
+ telemetrySdk.start();
2263
+ logger.info('Telemetry successfully initialized');
2264
+ telemetryInitialized = true;
2265
+ }
2266
+ } catch (error) {
2267
+ logger.error('Telemetry initialization failed', {
2268
+ error: error instanceof Error ? error.message : String(error),
2269
+ stack: error instanceof Error ? error.stack : void 0
2270
+ });
2271
+ logger.warn('Continuing without telemetry');
2272
+ telemetryInitialized = false;
2273
+ }
2274
+ if (telemetryOptions?.disabled) logger.info('Telemetry is disabled by configuration');
2275
+ else if (telemetryInitialized) logger.info('Telemetry initialized successfully');
2276
+ else logger.warn('Telemetry initialization failed, continuing without telemetry');
2277
+ logger.info('Initializing adapter', {
2278
+ storage: options.storage && 'object' == typeof options.storage ? options.storage.type || 'unknown' : 'unknown',
2279
+ clientVersion: options.clientVersion || 'not provided',
2280
+ appName,
2281
+ baseURL: baseUrlStr
2282
+ });
2283
+ const adapterResult = await promiseToResult(getAdapter(options), error_codes_ERROR_CODES.INITIALIZATION_FAILED);
2284
+ logger.debug('Adapter initialization result', {
2285
+ success: adapterResult.isOk()
2286
+ });
2287
+ return adapterResult.andThen((adapter)=>{
2288
+ const resolvedBaseURL = getBaseURL(baseUrlStr, basePathStr);
2289
+ const finalOptions = {
2290
+ ...options,
2291
+ baseURL: resolvedBaseURL ? new URL(resolvedBaseURL).origin : '',
2292
+ basePath: basePathStr || '/api/c15t',
2293
+ plugins: [
2294
+ ...options.plugins || [],
2295
+ ...getInternalPlugins(options)
2296
+ ],
2297
+ telemetry: telemetryOptions
2298
+ };
2299
+ const generateIdFunc = ({ model, size = 16 })=>finalOptions?.advanced?.generateId?.({
2300
+ model,
2301
+ size
2302
+ }) || id_generator_generateId(definition_getConsentTables(finalOptions)[model].entityPrefix);
2303
+ const registryContext = {
2304
+ adapter,
2305
+ options: finalOptions,
2306
+ logger,
2307
+ hooks: databaseHooks,
2308
+ generateId: generateIdFunc
2309
+ };
2310
+ const ctx = {
2311
+ appName: String(appName),
2312
+ options: finalOptions,
2313
+ trustedOrigins: options.trustedOrigins || [],
2314
+ baseURL: resolvedBaseURL || '',
2315
+ logger,
2316
+ generateId: generateIdFunc,
2317
+ adapter,
2318
+ registry: createRegistry(registryContext),
2319
+ tables: definition_getConsentTables(options)
2320
+ };
2321
+ return runPluginInit(ctx);
2322
+ });
2323
+ } catch (error) {
2324
+ const errorLogger = getLogger(options.logger);
2325
+ errorLogger.error('Initialization failed', {
2326
+ error: error instanceof Error ? error.message : String(error),
2327
+ stack: error instanceof Error ? error.stack : void 0
2328
+ });
2329
+ return failAsync(`Failed to initialize consent system: ${error instanceof Error ? error.message : String(error)}`, {
2330
+ code: error_codes_ERROR_CODES.INITIALIZATION_FAILED,
2331
+ meta: {
2332
+ error
2333
+ }
2334
+ });
2335
+ }
2336
+ };
2337
+ function runPluginInit(ctx) {
2338
+ try {
2339
+ let options = ctx.options;
2340
+ const plugins = options.plugins || [];
2341
+ let context = ctx;
2342
+ for (const plugin of plugins){
2343
+ const typedPlugin = plugin;
2344
+ if (typedPlugin.init) {
2345
+ const result = typedPlugin.init(ctx);
2346
+ if ('object' == typeof result) {
2347
+ if (result.options) options = (0, external_defu_namespaceObject.defu)(result.options, options);
2348
+ if (result.context) context = {
2349
+ ...context,
2350
+ ...result.context
2351
+ };
2352
+ }
2353
+ }
2354
+ }
2355
+ context.options = options;
2356
+ return (0, external_neverthrow_namespaceObject.ok)(context);
2357
+ } catch (error) {
2358
+ return fail(`Plugin initialization failed: ${error instanceof Error ? error.message : String(error)}`, {
2359
+ code: error_codes_ERROR_CODES.PLUGIN_INITIALIZATION_FAILED,
2360
+ meta: {
2361
+ error
2362
+ }
2363
+ });
2364
+ }
2365
+ }
2366
+ function getInternalPlugins(_options) {
2367
+ const plugins = [];
2368
+ return plugins;
2369
+ }
2370
+ const API_ROUTER_TRACER_NAME = '@doubletie/api-router';
2371
+ const getTracer = (options)=>{
2372
+ if (options?.telemetry?.tracer) return options.telemetry.tracer;
2373
+ return api_namespaceObject.trace.getTracer(API_ROUTER_TRACER_NAME);
2374
+ };
2375
+ const createRequestSpan = (method, path, options)=>{
2376
+ if (options?.telemetry?.disabled) return null;
2377
+ const tracer = getTracer(options);
2378
+ const span = tracer.startSpan(`${method} ${path}`, {
2379
+ attributes: {
2380
+ 'http.method': method,
2381
+ 'http.path': path,
2382
+ ...options?.telemetry?.defaultAttributes || {}
2383
+ }
2384
+ });
2385
+ return span;
2386
+ };
2387
+ const withRequestSpan = async (method, path, operation, options)=>{
2388
+ const span = createRequestSpan(method, path, options);
2389
+ if (!span) return operation();
2390
+ try {
2391
+ const result = await operation();
2392
+ span.setStatus({
2393
+ code: api_namespaceObject.SpanStatusCode.OK
2394
+ });
2395
+ return result;
2396
+ } catch (error) {
2397
+ handleSpanError(span, error);
2398
+ throw error;
2399
+ } finally{
2400
+ span.end();
2401
+ }
2402
+ };
2403
+ const handleSpanError = (span, error)=>{
2404
+ span.setStatus({
2405
+ code: api_namespaceObject.SpanStatusCode.ERROR,
2406
+ message: error instanceof Error ? error.message : String(error)
2407
+ });
2408
+ if (error instanceof Error) {
2409
+ span.setAttribute('error.type', error.name);
2410
+ span.setAttribute('error.message', error.message);
2411
+ if (error.stack) span.setAttribute('error.stack', error.stack);
2412
+ }
2413
+ };
2414
+ const STRIP_REGEX = /^(https?:\/\/)|(wss?:\/\/)|(\/+$)|:\d+/g;
2415
+ function isOriginTrusted(origin, trustedDomains, logger) {
2416
+ try {
2417
+ if (0 === trustedDomains.length) throw new Error('No trusted domains');
2418
+ logger?.debug(`Checking if origin ${origin} is trusted in ${trustedDomains}`);
2419
+ if (trustedDomains.includes('*')) {
2420
+ logger?.debug('Allowing all origins');
2421
+ return true;
2422
+ }
2423
+ const url = new URL(origin);
2424
+ const originHostname = url.hostname.toLowerCase();
2425
+ logger?.debug(`Parsed origin hostname: ${originHostname}`);
2426
+ return trustedDomains.some((domain)=>{
2427
+ if (!domain || '' === domain.trim()) {
2428
+ logger?.debug('Skipping empty domain');
2429
+ return false;
2430
+ }
2431
+ const strippedDomain = domain.replace(STRIP_REGEX, '').toLowerCase();
2432
+ logger?.debug(`Checking against stripped domain: ${strippedDomain}`);
2433
+ if (strippedDomain.startsWith('*.')) {
2434
+ const wildcardDomain = strippedDomain.slice(2);
2435
+ const parts = originHostname.split('.');
2436
+ const isValid = parts.length > 2 && originHostname.endsWith(wildcardDomain);
2437
+ logger?.debug(`Wildcard match result: ${isValid} ${originHostname} ends with ${wildcardDomain} ${parts.length > 2} ${originHostname.endsWith(wildcardDomain)}`);
2438
+ return isValid;
2439
+ }
2440
+ const isMatch = originHostname === strippedDomain;
2441
+ logger?.debug(`Exact match result: ${isMatch} ${originHostname} === ${strippedDomain}`);
2442
+ return isMatch;
2443
+ });
2444
+ } catch (error) {
2445
+ logger?.error('Error validating origin:', error);
2446
+ return false;
2447
+ }
2448
+ }
2449
+ const DEFAULT_IP_HEADERS = [
2450
+ 'x-client-ip',
2451
+ 'x-forwarded-for',
2452
+ 'cf-connecting-ip',
2453
+ 'fastly-client-ip',
2454
+ 'x-real-ip',
2455
+ 'x-cluster-client-ip',
2456
+ 'x-forwarded',
2457
+ 'forwarded-for',
2458
+ 'forwarded'
2459
+ ];
2460
+ function getIp(req, options) {
2461
+ const advanced = options.advanced || {};
2462
+ if (advanced?.ipAddress?.disableIpTracking) return null;
2463
+ const testIP = '127.0.0.1';
2464
+ if (isTest) return testIP;
2465
+ const ipHeaders = advanced?.ipAddress?.ipAddressHeaders || DEFAULT_IP_HEADERS;
2466
+ const headers = req instanceof Request ? req.headers : req;
2467
+ for (const key of ipHeaders){
2468
+ const value = headers.get(key);
2469
+ if (value) {
2470
+ const ip = value.split(',')[0]?.trim();
2471
+ if (ip) return ip;
2472
+ }
2473
+ }
2474
+ return null;
2475
+ }
2476
+ const contract_namespaceObject = require("@orpc/contract");
2477
+ const baseConsentSchema = external_zod_namespaceObject.z.object({
2478
+ subjectId: external_zod_namespaceObject.z.string().optional(),
2479
+ externalSubjectId: external_zod_namespaceObject.z.string().optional(),
2480
+ domain: external_zod_namespaceObject.z.string().regex(/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i, 'invalid domain'),
2481
+ type: PolicyTypeSchema,
2482
+ metadata: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional()
2483
+ });
2484
+ const cookieBannerSchema = baseConsentSchema.extend({
2485
+ type: external_zod_namespaceObject.z.literal('cookie_banner'),
2486
+ preferences: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.boolean())
2487
+ });
2488
+ const policyBasedSchema = baseConsentSchema.extend({
2489
+ type: external_zod_namespaceObject.z["enum"]([
2490
+ 'privacy_policy',
2491
+ 'dpa',
2492
+ 'terms_and_conditions'
2493
+ ]),
2494
+ policyId: external_zod_namespaceObject.z.string().optional(),
2495
+ preferences: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.boolean()).optional()
2496
+ });
2497
+ const otherConsentSchema = baseConsentSchema.extend({
2498
+ type: external_zod_namespaceObject.z["enum"]([
2499
+ 'marketing_communications',
2500
+ 'age_verification',
2501
+ 'other'
2502
+ ]),
2503
+ preferences: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.boolean()).optional()
2504
+ });
2505
+ const postConsentContract = contract_namespaceObject.oc.route({
2506
+ method: 'POST',
2507
+ path: '/consent/set',
2508
+ description: `Records a user's consent preferences and creates necessary consent records.
2509
+ This endpoint handles various types of consent submissions:
2510
+
2511
+ 1. Cookie Banner Consent:
2512
+ - Records granular cookie preferences
2513
+ - Supports multiple consent purposes
2514
+ - Creates audit trail for compliance
2515
+
2516
+ 2. Policy-Based Consent:
2517
+ - Privacy Policy acceptance
2518
+ - Data Processing Agreement (DPA) consent
2519
+ - Terms and Conditions acceptance
2520
+ - Links consent to specific policy versions
2521
+
2522
+ 3. Other Consent Types:
2523
+ - Marketing communications preferences
2524
+ - Age verification consent
2525
+ - Custom consent types
2526
+
2527
+ The endpoint performs the following operations:
2528
+ - Creates or retrieves subject records
2529
+ - Validates domain and policy information
2530
+ - Creates consent records with audit trails
2531
+ - Records consent purposes and preferences
2532
+ - Generates audit logs for compliance
2533
+
2534
+ Use this endpoint to record user consent and maintain a compliant consent management system.`,
2535
+ tags: [
2536
+ 'consent',
2537
+ 'cookie-banner'
2538
+ ]
2539
+ }).errors({
2540
+ INPUT_VALIDATION_FAILED: {
2541
+ status: 422,
2542
+ message: 'Invalid input parameters',
2543
+ data: external_zod_namespaceObject.z.object({
2544
+ formErrors: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
2545
+ fieldErrors: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.string(), external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()))
2546
+ })
2547
+ },
2548
+ SUBJECT_CREATION_FAILED: {
2549
+ status: 400,
2550
+ message: 'Failed to create or find subject',
2551
+ data: external_zod_namespaceObject.z.object({
2552
+ subjectId: external_zod_namespaceObject.z.string().optional(),
2553
+ externalSubjectId: external_zod_namespaceObject.z.string().optional()
2554
+ })
2555
+ },
2556
+ DOMAIN_CREATION_FAILED: {
2557
+ status: 500,
2558
+ message: 'Failed to create or find domain',
2559
+ data: external_zod_namespaceObject.z.object({
2560
+ domain: external_zod_namespaceObject.z.string()
2561
+ })
2562
+ },
2563
+ POLICY_NOT_FOUND: {
2564
+ status: 404,
2565
+ message: 'Policy not found',
2566
+ data: external_zod_namespaceObject.z.object({
2567
+ policyId: external_zod_namespaceObject.z.string(),
2568
+ type: external_zod_namespaceObject.z.string()
2569
+ })
2570
+ },
2571
+ POLICY_INACTIVE: {
2572
+ status: 409,
2573
+ message: 'Policy is not active',
2574
+ data: external_zod_namespaceObject.z.object({
2575
+ policyId: external_zod_namespaceObject.z.string(),
2576
+ type: external_zod_namespaceObject.z.string()
2577
+ })
2578
+ },
2579
+ POLICY_CREATION_FAILED: {
2580
+ status: 500,
2581
+ message: 'Failed to create or find policy',
2582
+ data: external_zod_namespaceObject.z.object({
2583
+ type: external_zod_namespaceObject.z.string()
2584
+ })
2585
+ },
2586
+ PURPOSE_CREATION_FAILED: {
2587
+ status: 500,
2588
+ message: 'Failed to create consent purpose',
2589
+ data: external_zod_namespaceObject.z.object({
2590
+ purposeCode: external_zod_namespaceObject.z.string()
2591
+ })
2592
+ },
2593
+ CONSENT_CREATION_FAILED: {
2594
+ status: 500,
2595
+ message: 'Failed to create consent record',
2596
+ data: external_zod_namespaceObject.z.object({
2597
+ subjectId: external_zod_namespaceObject.z.string(),
2598
+ domain: external_zod_namespaceObject.z.string()
2599
+ })
2600
+ }
2601
+ }).input(external_zod_namespaceObject.z.discriminatedUnion('type', [
2602
+ cookieBannerSchema,
2603
+ policyBasedSchema,
2604
+ otherConsentSchema
2605
+ ])).output(external_zod_namespaceObject.z.object({
2606
+ id: external_zod_namespaceObject.z.string(),
2607
+ subjectId: external_zod_namespaceObject.z.string().optional(),
2608
+ externalSubjectId: external_zod_namespaceObject.z.string().optional(),
2609
+ domainId: external_zod_namespaceObject.z.string(),
2610
+ domain: external_zod_namespaceObject.z.string(),
2611
+ type: PolicyTypeSchema,
2612
+ status: external_zod_namespaceObject.z.string(),
2613
+ recordId: external_zod_namespaceObject.z.string(),
2614
+ metadata: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.unknown()).optional(),
2615
+ givenAt: external_zod_namespaceObject.z.date()
2616
+ }));
2617
+ const JurisdictionMessages = {
2618
+ GDPR: 'GDPR or equivalent regulations require a cookie banner.',
2619
+ CH: 'Switzerland requires similar data protection measures.',
2620
+ BR: "Brazil's LGPD requires consent for cookies.",
2621
+ PIPEDA: 'PIPEDA requires consent for data collection.',
2622
+ AU: "Australia's Privacy Act mandates transparency about data collection.",
2623
+ APPI: "Japan's APPI requires consent for data collection.",
2624
+ PIPA: "South Korea's PIPA requires consent for data collection.",
2625
+ NONE: 'No specific requirements'
2626
+ };
2627
+ const JurisdictionCodeSchema = external_zod_namespaceObject.z["enum"]([
2628
+ 'GDPR',
2629
+ 'CH',
2630
+ 'BR',
2631
+ 'PIPEDA',
2632
+ 'AU',
2633
+ 'APPI',
2634
+ 'PIPA',
2635
+ 'NONE'
2636
+ ]);
2637
+ const JurisdictionInfoSchema = external_zod_namespaceObject.z.object({
2638
+ code: JurisdictionCodeSchema,
2639
+ message: external_zod_namespaceObject.z.string()
2640
+ });
2641
+ const showConsentBannerContract = contract_namespaceObject.oc.route({
2642
+ method: 'GET',
2643
+ path: '/show-consent-banner',
2644
+ description: `Determines if a user should see a consent banner based on their location and applicable privacy regulations.
2645
+ This endpoint performs the following checks:
2646
+
2647
+ 1. Detects the user's location using various header information:
2648
+ - Cloudflare country headers
2649
+ - Vercel IP country headers
2650
+ - AWS CloudFront headers
2651
+ - Custom country code headers
2652
+
2653
+ 2. Determines the applicable jurisdiction based on the location:
2654
+ - GDPR (EU/EEA/UK)
2655
+ - Swiss Data Protection Act
2656
+ - LGPD (Brazil)
2657
+ - PIPEDA (Canada)
2658
+ - Australian Privacy Principles
2659
+ - APPI (Japan)
2660
+ - PIPA (South Korea)
2661
+
2662
+ 3. Returns detailed information about:
2663
+ - Whether to show the consent banner
2664
+ - The applicable jurisdiction and its requirements
2665
+ - The user's detected location (country and region)
2666
+
2667
+ Use this endpoint to implement geo-targeted consent banners and ensure compliance with regional privacy regulations.`,
2668
+ tags: [
2669
+ 'cookie-banner'
2670
+ ]
2671
+ }).output(external_zod_namespaceObject.z.object({
2672
+ showConsentBanner: external_zod_namespaceObject.z.boolean(),
2673
+ jurisdiction: JurisdictionInfoSchema,
2674
+ location: external_zod_namespaceObject.z.object({
2675
+ countryCode: external_zod_namespaceObject.z.string().nullable(),
2676
+ regionCode: external_zod_namespaceObject.z.string().nullable()
2677
+ })
2678
+ }));
2679
+ const verifyConsentInputSchema = external_zod_namespaceObject.z.object({
2680
+ subjectId: external_zod_namespaceObject.z.string().optional(),
2681
+ externalSubjectId: external_zod_namespaceObject.z.string().optional(),
2682
+ domain: external_zod_namespaceObject.z.string(),
2683
+ type: PolicyTypeSchema,
2684
+ policyId: external_zod_namespaceObject.z.string().optional(),
2685
+ preferences: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()).optional()
2686
+ }).strict();
2687
+ const verify_contract_consentSchema = external_zod_namespaceObject.z.object({
2688
+ id: external_zod_namespaceObject.z.string(),
2689
+ purposeIds: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string())
2690
+ }).passthrough();
2691
+ const verifyConsentContract = contract_namespaceObject.oc.route({
2692
+ method: 'POST',
2693
+ path: '/consent/verify',
2694
+ description: `Verifies if a user has given valid consent for a specific policy and domain.
2695
+ This endpoint performs comprehensive consent verification by:
2696
+
2697
+ 1. Validating the subject's identity (using subjectId or externalSubjectId)
2698
+ 2. Verifying the domain's existence and validity
2699
+ 3. Checking if the specified policy exists and is active
2700
+ 4. Validating that all required purposes have been consented to
2701
+ 5. Ensuring the consent record is current and valid
2702
+
2703
+ The endpoint supports different types of consent verification:
2704
+ - Cookie banner consent verification
2705
+ - Privacy policy consent verification
2706
+ - Terms and conditions verification
2707
+ - Marketing communications consent verification
2708
+ - Age verification
2709
+ - Custom consent types
2710
+
2711
+ Use this endpoint to ensure compliance with privacy regulations and to verify user consent before processing personal data.`,
2712
+ tags: [
2713
+ 'consent'
2714
+ ]
2715
+ }).errors({
2716
+ INPUT_VALIDATION_FAILED: {
2717
+ status: 422,
2718
+ message: 'Invalid input parameters',
2719
+ data: external_zod_namespaceObject.z.object({
2720
+ formErrors: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
2721
+ fieldErrors: external_zod_namespaceObject.z.record(external_zod_namespaceObject.z.string(), external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()).optional())
2722
+ })
2723
+ },
2724
+ SUBJECT_NOT_FOUND: {
2725
+ status: 404,
2726
+ message: 'Subject not found',
2727
+ data: external_zod_namespaceObject.z.object({
2728
+ subjectId: external_zod_namespaceObject.z.string().optional(),
2729
+ externalSubjectId: external_zod_namespaceObject.z.string().optional()
2730
+ })
2731
+ },
2732
+ DOMAIN_NOT_FOUND: {
2733
+ status: 404,
2734
+ message: 'Domain not found',
2735
+ data: external_zod_namespaceObject.z.object({
2736
+ domain: external_zod_namespaceObject.z.string()
2737
+ })
2738
+ },
2739
+ POLICY_NOT_FOUND: {
2740
+ status: 404,
2741
+ message: 'Policy not found or invalid',
2742
+ data: external_zod_namespaceObject.z.object({
2743
+ policyId: external_zod_namespaceObject.z.string(),
2744
+ type: external_zod_namespaceObject.z.string()
2745
+ })
2746
+ },
2747
+ PURPOSES_NOT_FOUND: {
2748
+ status: 404,
2749
+ message: 'Could not find all specified purposes',
2750
+ data: external_zod_namespaceObject.z.object({
2751
+ preferences: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()),
2752
+ foundPurposes: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string())
2753
+ })
2754
+ },
2755
+ COOKIE_BANNER_PREFERENCES_REQUIRED: {
2756
+ status: 400,
2757
+ message: 'Preferences are required for cookie banner consent',
2758
+ data: external_zod_namespaceObject.z.object({
2759
+ type: external_zod_namespaceObject.z.literal('cookie_banner')
2760
+ })
2761
+ },
2762
+ NO_CONSENT_FOUND: {
2763
+ status: 404,
2764
+ message: 'No consent found for the given policy',
2765
+ data: external_zod_namespaceObject.z.object({
2766
+ policyId: external_zod_namespaceObject.z.string(),
2767
+ subjectId: external_zod_namespaceObject.z.string(),
2768
+ domainId: external_zod_namespaceObject.z.string()
2769
+ })
2770
+ }
2771
+ }).input(verifyConsentInputSchema).output(external_zod_namespaceObject.z.object({
2772
+ isValid: external_zod_namespaceObject.z.boolean(),
2773
+ reasons: external_zod_namespaceObject.z.array(external_zod_namespaceObject.z.string()).optional(),
2774
+ consent: verify_contract_consentSchema.optional()
2775
+ }));
2776
+ const consentContracts = {
2777
+ post: postConsentContract,
2778
+ showBanner: showConsentBannerContract,
2779
+ verify: verifyConsentContract
2780
+ };
2781
+ const statusContract = contract_namespaceObject.oc.route({
2782
+ method: 'GET',
2783
+ path: '/status',
2784
+ description: `Returns the current operational status and health metrics of the service.
2785
+ This endpoint provides real-time information about:
2786
+ - Overall service status (ok/error)
2787
+ - Current API version
2788
+ - Server timestamp
2789
+ - Storage system status and availability
2790
+ - Client information (IP, User Agent, Region)
2791
+
2792
+ Use this endpoint for health checks, monitoring, and service status verification.`,
2793
+ tags: [
2794
+ 'meta'
2795
+ ]
2796
+ }).output(external_zod_namespaceObject.z.object({
2797
+ status: external_zod_namespaceObject.z["enum"]([
2798
+ 'ok',
2799
+ 'error'
2800
+ ]),
2801
+ version: external_zod_namespaceObject.z.string(),
2802
+ timestamp: external_zod_namespaceObject.z.date(),
2803
+ storage: external_zod_namespaceObject.z.object({
2804
+ type: external_zod_namespaceObject.z.string(),
2805
+ available: external_zod_namespaceObject.z.boolean()
2806
+ }),
2807
+ client: external_zod_namespaceObject.z.object({
2808
+ ip: external_zod_namespaceObject.z.string().nullable(),
2809
+ userAgent: external_zod_namespaceObject.z.string().nullable(),
2810
+ region: external_zod_namespaceObject.z.object({
2811
+ countryCode: external_zod_namespaceObject.z.string().nullable(),
2812
+ regionCode: external_zod_namespaceObject.z.string().nullable()
2813
+ })
2814
+ })
2815
+ }));
2816
+ const metaContracts = {
2817
+ status: statusContract
2818
+ };
2819
+ const contracts_config = {
2820
+ consent: consentContracts,
2821
+ meta: metaContracts
2822
+ };
2823
+ const os = (0, server_namespaceObject.implement)(contracts_config);
2824
+ const postConsent = os.consent.post.handler(async ({ input, context })=>{
2825
+ const typedContext = context;
2826
+ const logger = typedContext.logger;
2827
+ logger.info('Handling post-consent request');
2828
+ const { type, subjectId, externalSubjectId, domain, metadata, preferences } = input;
2829
+ logger.debug('Request parameters', {
2830
+ type,
2831
+ subjectId,
2832
+ externalSubjectId,
2833
+ domain
2834
+ });
2835
+ try {
2836
+ const subject = await typedContext.registry.findOrCreateSubject({
2837
+ subjectId,
2838
+ externalSubjectId,
2839
+ ipAddress: typedContext.ipAddress || 'unknown'
2840
+ });
2841
+ if (!subject) throw new server_namespaceObject.ORPCError('SUBJECT_CREATION_FAILED', {
2842
+ data: {
2843
+ subjectId,
2844
+ externalSubjectId
2845
+ }
2846
+ });
2847
+ logger.debug('Subject found/created', {
2848
+ subjectId: subject.id
2849
+ });
2850
+ const domainRecord = await typedContext.registry.findOrCreateDomain(domain);
2851
+ if (!domainRecord) throw new server_namespaceObject.ORPCError('DOMAIN_CREATION_FAILED', {
2852
+ data: {
2853
+ domain
2854
+ }
2855
+ });
2856
+ const now = new Date();
2857
+ let policyId;
2858
+ let purposeIds = [];
2859
+ if ('policyId' in input && input.policyId) {
2860
+ policyId = input.policyId;
2861
+ const policy = await typedContext.registry.findConsentPolicyById(policyId);
2862
+ if (!policy) throw new server_namespaceObject.ORPCError('POLICY_NOT_FOUND', {
2863
+ data: {
2864
+ policyId,
2865
+ type
2866
+ }
2867
+ });
2868
+ if (!policy.isActive) throw new server_namespaceObject.ORPCError('POLICY_INACTIVE', {
2869
+ data: {
2870
+ policyId,
2871
+ type
2872
+ }
2873
+ });
2874
+ } else {
2875
+ const policy = await typedContext.registry.findOrCreatePolicy(type);
2876
+ if (!policy) throw new server_namespaceObject.ORPCError('POLICY_CREATION_FAILED', {
2877
+ data: {
2878
+ type
2879
+ }
2880
+ });
2881
+ policyId = policy.id;
2882
+ }
2883
+ if (preferences) {
2884
+ const consentedPurposes = Object.entries(preferences).filter(([_, isConsented])=>isConsented).map(([purposeCode])=>purposeCode);
2885
+ const existingPurposes = await Promise.all(consentedPurposes.map((purposeCode)=>typedContext.registry.findConsentPurposeByCode(purposeCode)));
2886
+ const purposesToCreate = consentedPurposes.filter((_purposeCode, index)=>!existingPurposes[index]);
2887
+ const createdPurposes = await Promise.all(purposesToCreate.map((purposeCode)=>typedContext.registry.createConsentPurpose({
2888
+ code: purposeCode,
2889
+ name: purposeCode,
2890
+ description: `Auto-created consentPurpose for ${purposeCode}`,
2891
+ isActive: true,
2892
+ isEssential: false,
2893
+ legalBasis: 'consent',
2894
+ createdAt: now,
2895
+ updatedAt: now
2896
+ })));
2897
+ purposeIds = [
2898
+ ...existingPurposes.filter((p)=>null !== p).map((p)=>p.id),
2899
+ ...createdPurposes.filter((p)=>null !== p).map((p)=>p.id)
2900
+ ];
2901
+ if (purposeIds.length !== consentedPurposes.length) throw new server_namespaceObject.ORPCError('PURPOSE_CREATION_FAILED', {
2902
+ data: {
2903
+ purposeCode: purposesToCreate[purposeIds.length - consentedPurposes.length]
2904
+ }
2905
+ });
2906
+ }
2907
+ const result = await typedContext.adapter.transaction({
2908
+ callback: async (tx)=>{
2909
+ const consentRecord = await tx.create({
2910
+ model: 'consent',
2911
+ data: {
2912
+ subjectId: subject.id,
2913
+ domainId: domainRecord.id,
2914
+ policyId,
2915
+ purposeIds,
2916
+ status: 'active',
2917
+ isActive: true,
2918
+ givenAt: now,
2919
+ ipAddress: typedContext.ipAddress || 'unknown',
2920
+ agent: typedContext.userAgent || 'unknown',
2921
+ history: []
2922
+ }
2923
+ });
2924
+ const record = await tx.create({
2925
+ model: 'consentRecord',
2926
+ data: {
2927
+ subjectId: subject.id,
2928
+ consentId: consentRecord.id,
2929
+ actionType: 'consent_given',
2930
+ details: metadata,
2931
+ createdAt: now
2932
+ }
2933
+ });
2934
+ await tx.create({
2935
+ model: 'auditLog',
2936
+ data: {
2937
+ subjectId: subject.id,
2938
+ entityType: 'consent',
2939
+ entityId: consentRecord.id,
2940
+ actionType: 'consent_given',
2941
+ details: {
2942
+ consentId: consentRecord.id,
2943
+ type
2944
+ },
2945
+ timestamp: now,
2946
+ ipAddress: typedContext.ipAddress || 'unknown',
2947
+ agent: typedContext.userAgent || 'unknown'
2948
+ }
2949
+ });
2950
+ return {
2951
+ consent: consentRecord,
2952
+ record
2953
+ };
2954
+ }
2955
+ });
2956
+ if (!result || !result.consent || !result.record) throw new server_namespaceObject.ORPCError('CONSENT_CREATION_FAILED', {
2957
+ data: {
2958
+ subjectId: subject.id,
2959
+ domain
2960
+ }
2961
+ });
2962
+ return {
2963
+ id: result.consent.id,
2964
+ subjectId: subject.id,
2965
+ externalSubjectId: subject.externalId ?? void 0,
2966
+ domainId: domainRecord.id,
2967
+ domain: domainRecord.name,
2968
+ type,
2969
+ status: result.consent.status,
2970
+ recordId: result.record.id,
2971
+ metadata,
2972
+ givenAt: result.consent.givenAt
2973
+ };
2974
+ } catch (error) {
2975
+ logger.error('Error in post-consent handler', {
2976
+ error: error instanceof Error ? error.message : String(error),
2977
+ errorType: error instanceof Error ? error.constructor.name : typeof error
2978
+ });
2979
+ if (error instanceof server_namespaceObject.ORPCError) throw error;
2980
+ throw new server_namespaceObject.ORPCError('INTERNAL_SERVER_ERROR', {
2981
+ message: error instanceof Error ? error.message : String(error)
2982
+ });
2983
+ }
2984
+ });
2985
+ const show_banner_handler_showConsentBanner = os.consent.showBanner.handler(({ context })=>{
2986
+ const typedContext = context;
2987
+ const headers = typedContext.headers;
2988
+ if (!headers) throw new server_namespaceObject.ORPCError('LOCATION_DETECTION_FAILED', {
2989
+ data: {
2990
+ reason: 'No headers found in request context'
2991
+ }
2992
+ });
2993
+ const normalizeHeader = (value)=>{
2994
+ if (!value) return null;
2995
+ return Array.isArray(value) ? value[0] ?? null : value;
2996
+ };
2997
+ const countryCode = normalizeHeader(headers.get('cf-ipcountry')) ?? normalizeHeader(headers.get('x-vercel-ip-country')) ?? normalizeHeader(headers.get('x-amz-cf-ipcountry')) ?? normalizeHeader(headers.get('x-country-code'));
2998
+ const regionCode = normalizeHeader(headers.get('x-vercel-ip-country-region')) ?? normalizeHeader(headers.get('x-region-code'));
2999
+ const { showConsentBanner, jurisdictionCode, message } = checkJurisdiction(countryCode);
3000
+ return {
3001
+ showConsentBanner,
3002
+ jurisdiction: {
3003
+ code: jurisdictionCode,
3004
+ message
3005
+ },
3006
+ location: {
3007
+ countryCode,
3008
+ regionCode
3009
+ }
3010
+ };
3011
+ });
3012
+ function checkJurisdiction(countryCode) {
3013
+ const jurisdictions = {
3014
+ EU: new Set([
3015
+ 'AT',
3016
+ 'BE',
3017
+ 'BG',
3018
+ 'HR',
3019
+ 'CY',
3020
+ 'CZ',
3021
+ 'DK',
3022
+ 'EE',
3023
+ 'FI',
3024
+ 'FR',
3025
+ 'DE',
3026
+ 'GR',
3027
+ 'HU',
3028
+ 'IE',
3029
+ 'IT',
3030
+ 'LV',
3031
+ 'LT',
3032
+ 'LU',
3033
+ 'MT',
3034
+ 'NL',
3035
+ 'PL',
3036
+ 'PT',
3037
+ 'RO',
3038
+ 'SK',
3039
+ 'SI',
3040
+ 'ES',
3041
+ 'SE'
3042
+ ]),
3043
+ EEA: new Set([
3044
+ 'IS',
3045
+ 'NO',
3046
+ 'LI'
3047
+ ]),
3048
+ UK: new Set([
3049
+ 'GB'
3050
+ ]),
3051
+ CH: new Set([
3052
+ 'CH'
3053
+ ]),
3054
+ BR: new Set([
3055
+ 'BR'
3056
+ ]),
3057
+ CA: new Set([
3058
+ 'CA'
3059
+ ]),
3060
+ AU: new Set([
3061
+ 'AU'
3062
+ ]),
3063
+ JP: new Set([
3064
+ 'JP'
3065
+ ]),
3066
+ KR: new Set([
3067
+ 'KR'
3068
+ ])
3069
+ };
3070
+ let showConsentBanner = false;
3071
+ let jurisdictionCode = 'NONE';
3072
+ if (countryCode) {
3073
+ const jurisdictionMap = [
3074
+ {
3075
+ sets: [
3076
+ jurisdictions.EU,
3077
+ jurisdictions.EEA,
3078
+ jurisdictions.UK
3079
+ ],
3080
+ code: 'GDPR'
3081
+ },
3082
+ {
3083
+ sets: [
3084
+ jurisdictions.CH
3085
+ ],
3086
+ code: 'CH'
3087
+ },
3088
+ {
3089
+ sets: [
3090
+ jurisdictions.BR
3091
+ ],
3092
+ code: 'BR'
3093
+ },
3094
+ {
3095
+ sets: [
3096
+ jurisdictions.CA
3097
+ ],
3098
+ code: 'PIPEDA'
3099
+ },
3100
+ {
3101
+ sets: [
3102
+ jurisdictions.AU
3103
+ ],
3104
+ code: 'AU'
3105
+ },
3106
+ {
3107
+ sets: [
3108
+ jurisdictions.JP
3109
+ ],
3110
+ code: 'APPI'
3111
+ },
3112
+ {
3113
+ sets: [
3114
+ jurisdictions.KR
3115
+ ],
3116
+ code: 'PIPA'
3117
+ }
3118
+ ];
3119
+ for (const { sets, code } of jurisdictionMap)if (sets.some((set)=>set.has(countryCode))) {
3120
+ showConsentBanner = true;
3121
+ jurisdictionCode = code;
3122
+ break;
3123
+ }
3124
+ }
3125
+ const message = JurisdictionMessages[jurisdictionCode];
3126
+ return {
3127
+ showConsentBanner,
3128
+ jurisdictionCode,
3129
+ message
3130
+ };
3131
+ }
3132
+ const verifyConsent = os.consent.verify.handler(async ({ input, context })=>{
3133
+ const typedContext = context;
3134
+ const logger = typedContext.logger;
3135
+ logger.info('Handling verify-consent request');
3136
+ const { type, subjectId, externalSubjectId, domain, policyId, preferences } = input;
3137
+ logger.debug('Request parameters', {
3138
+ type,
3139
+ subjectId,
3140
+ externalSubjectId,
3141
+ domain,
3142
+ policyId,
3143
+ preferences
3144
+ });
3145
+ try {
3146
+ const subject = await typedContext.registry.findOrCreateSubject({
3147
+ subjectId,
3148
+ externalSubjectId,
3149
+ ipAddress: typedContext.ipAddress || 'unknown'
3150
+ });
3151
+ if (!subject) throw new server_namespaceObject.ORPCError('SUBJECT_NOT_FOUND', {
3152
+ data: {
3153
+ subjectId,
3154
+ externalSubjectId
3155
+ }
3156
+ });
3157
+ const domainRecord = await typedContext.registry.findDomain(domain);
3158
+ if (!domainRecord) throw new server_namespaceObject.ORPCError('DOMAIN_NOT_FOUND', {
3159
+ data: {
3160
+ domain
3161
+ }
3162
+ });
3163
+ if ('cookie_banner' === type && (!preferences || 0 === preferences.length)) throw new server_namespaceObject.ORPCError('COOKIE_BANNER_PREFERENCES_REQUIRED', {
3164
+ data: {
3165
+ type: 'cookie_banner'
3166
+ }
3167
+ });
3168
+ const purposePromises = preferences?.map((purpose)=>typedContext.registry.findConsentPurposeByCode(purpose));
3169
+ const rawPurposes = await Promise.all(purposePromises ?? []);
3170
+ const purposeIds = rawPurposes.filter((purpose)=>null !== purpose).map((purpose)=>purpose.id);
3171
+ if (purposeIds.length !== (preferences?.length ?? 0)) throw new server_namespaceObject.ORPCError('PURPOSES_NOT_FOUND', {
3172
+ data: {
3173
+ preferences: preferences ?? [],
3174
+ foundPurposes: rawPurposes.filter((p)=>null !== p).map((p)=>p.code)
3175
+ }
3176
+ });
3177
+ if (policyId) {
3178
+ const policy = await typedContext.registry.findConsentPolicyById(policyId);
3179
+ if (!policy || policy.type !== type) throw new server_namespaceObject.ORPCError('POLICY_NOT_FOUND', {
3180
+ data: {
3181
+ policyId,
3182
+ type
3183
+ }
3184
+ });
3185
+ return await checkPolicyConsent({
3186
+ policyId: policy.id,
3187
+ subjectId: subject.id,
3188
+ domainId: domainRecord.id,
3189
+ purposeIds,
3190
+ type,
3191
+ context: typedContext
3192
+ });
3193
+ }
3194
+ const latestPolicy = await typedContext.registry.findOrCreatePolicy(type);
3195
+ if (!latestPolicy) throw new server_namespaceObject.ORPCError('POLICY_NOT_FOUND', {
3196
+ data: {
3197
+ policyId: 'latest',
3198
+ type
3199
+ }
3200
+ });
3201
+ return await checkPolicyConsent({
3202
+ policyId: latestPolicy.id,
3203
+ subjectId: subject.id,
3204
+ domainId: domainRecord.id,
3205
+ purposeIds,
3206
+ type,
3207
+ context: typedContext
3208
+ });
3209
+ } catch (error) {
3210
+ logger.error('Error in verify-consent handler', {
3211
+ error: error instanceof Error ? error.message : String(error),
3212
+ errorType: error instanceof Error ? error.constructor.name : typeof error
3213
+ });
3214
+ if (error instanceof server_namespaceObject.ORPCError) throw error;
3215
+ throw new server_namespaceObject.ORPCError('INTERNAL_SERVER_ERROR', {
3216
+ message: error instanceof Error ? error.message : String(error)
3217
+ });
3218
+ }
3219
+ });
3220
+ async function checkPolicyConsent({ policyId, subjectId, domainId, purposeIds, type, context }) {
3221
+ const { registry, adapter } = context;
3222
+ const rawConsents = await adapter.findMany({
3223
+ model: 'consent',
3224
+ where: [
3225
+ {
3226
+ field: 'subjectId',
3227
+ value: subjectId
3228
+ },
3229
+ {
3230
+ field: 'policyId',
3231
+ value: policyId
3232
+ },
3233
+ {
3234
+ field: 'domainId',
3235
+ value: domainId
3236
+ }
3237
+ ],
3238
+ sortBy: {
3239
+ field: 'givenAt',
3240
+ direction: 'desc'
3241
+ }
3242
+ });
3243
+ const filteredConsents = rawConsents.filter((consent)=>{
3244
+ if (!purposeIds) return true;
3245
+ return purposeIds.every((id)=>consent.purposeIds.some((purposeId)=>purposeId === id));
3246
+ });
3247
+ await registry.createAuditLog({
3248
+ subjectId,
3249
+ entityType: 'consent_policy',
3250
+ entityId: policyId,
3251
+ actionType: 'verify_consent',
3252
+ metadata: {
3253
+ type,
3254
+ policyId,
3255
+ purposeIds,
3256
+ success: 0 !== filteredConsents.length,
3257
+ ...filteredConsents.length > 0 ? {
3258
+ consentId: filteredConsents[0]?.id
3259
+ } : {}
3260
+ }
3261
+ });
3262
+ if (0 === rawConsents.length) throw new server_namespaceObject.ORPCError('NO_CONSENT_FOUND', {
3263
+ data: {
3264
+ policyId,
3265
+ subjectId,
3266
+ domainId
3267
+ }
3268
+ });
3269
+ if (0 === filteredConsents.length) throw new server_namespaceObject.ORPCError('NO_CONSENT_FOUND', {
3270
+ data: {
3271
+ policyId,
3272
+ subjectId,
3273
+ domainId
3274
+ }
3275
+ });
3276
+ return {
3277
+ isValid: true,
3278
+ consent: filteredConsents[0]
3279
+ };
3280
+ }
3281
+ const consentHandlers = {
3282
+ post: postConsent,
3283
+ showBanner: show_banner_handler_showConsentBanner,
3284
+ verify: verifyConsent
3285
+ };
3286
+ const statusHandler = os.meta.status.handler(({ context })=>{
3287
+ const typedContext = context;
3288
+ const headers = typedContext.headers;
3289
+ const normalizeHeader = (value)=>{
3290
+ if (!value) return null;
3291
+ return Array.isArray(value) ? value[0] ?? null : value;
3292
+ };
3293
+ const countryCode = normalizeHeader(headers?.get('cf-ipcountry')) ?? normalizeHeader(headers?.get('x-vercel-ip-country')) ?? normalizeHeader(headers?.get('x-amz-cf-ipcountry')) ?? normalizeHeader(headers?.get('x-country-code'));
3294
+ const regionCode = normalizeHeader(headers?.get('x-vercel-ip-country-region')) ?? normalizeHeader(headers?.get('x-region-code'));
3295
+ return {
3296
+ status: 'ok',
3297
+ version: package_namespaceObject.i8,
3298
+ timestamp: new Date(),
3299
+ storage: {
3300
+ type: typedContext.adapter?.id ?? 'MemoryAdapter',
3301
+ available: !!typedContext.adapter
3302
+ },
3303
+ client: {
3304
+ ip: typedContext.ipAddress ?? null,
3305
+ userAgent: typedContext.userAgent ?? null,
3306
+ region: {
3307
+ countryCode,
3308
+ regionCode
3309
+ }
3310
+ }
3311
+ };
3312
+ });
3313
+ const metaHandlers = {
3314
+ status: statusHandler
3315
+ };
3316
+ const router = os.router({
3317
+ consent: consentHandlers,
3318
+ meta: metaHandlers
3319
+ });
3320
+ const c15tInstance = (options)=>{
3321
+ const contextPromise = init(options);
3322
+ const corsOptions = options.trustedOrigins ? {
3323
+ origin: options.trustedOrigins.includes('*') ? '*' : options.trustedOrigins,
3324
+ credentials: true,
3325
+ methods: [
3326
+ 'GET',
3327
+ 'POST',
3328
+ 'PUT',
3329
+ 'DELETE',
3330
+ 'OPTIONS',
3331
+ 'PATCH'
3332
+ ],
3333
+ allowedHeaders: [
3334
+ 'Content-Type',
3335
+ 'Authorization',
3336
+ 'X-Request-ID'
3337
+ ],
3338
+ maxAge: 86400
3339
+ } : {
3340
+ origin: '*',
3341
+ credentials: false,
3342
+ methods: [
3343
+ 'GET',
3344
+ 'POST',
3345
+ 'PUT',
3346
+ 'DELETE',
3347
+ 'OPTIONS',
3348
+ 'PATCH'
3349
+ ],
3350
+ allowedHeaders: [
3351
+ 'Content-Type',
3352
+ 'Authorization',
3353
+ 'X-Request-ID'
3354
+ ],
3355
+ maxAge: 86400
3356
+ };
3357
+ const rpcHandler = new fetch_namespaceObject.OpenAPIHandler(router, {
3358
+ plugins: [
3359
+ new plugins_namespaceObject.CORSPlugin(corsOptions)
3360
+ ]
3361
+ });
3362
+ const openAPIGenerator = new openapi_namespaceObject.OpenAPIGenerator({
3363
+ schemaConverters: [
3364
+ new zod_namespaceObject.ZodToJsonSchemaConverter()
3365
+ ]
3366
+ });
3367
+ const openApiConfig = {
3368
+ enabled: true,
3369
+ specPath: '/spec.json',
3370
+ docsPath: '/docs',
3371
+ ...options.openapi || {}
3372
+ };
3373
+ const defaultOpenApiOptions = {
3374
+ info: {
3375
+ title: options.appName || 'c15t API',
3376
+ version: package_namespaceObject.i8,
3377
+ description: 'API for consent management'
3378
+ },
3379
+ servers: [
3380
+ {
3381
+ url: '/'
3382
+ }
3383
+ ],
3384
+ security: [
3385
+ {
3386
+ bearerAuth: []
3387
+ }
3388
+ ]
3389
+ };
3390
+ const processIp = (request, context)=>{
3391
+ const ip = getIp(request, options);
3392
+ if (ip) context.ipAddress = ip;
3393
+ return context;
3394
+ };
3395
+ const processCors = (request, context)=>{
3396
+ const origin = request.headers.get('origin');
3397
+ if (origin && options.trustedOrigins) {
3398
+ const trusted = isOriginTrusted(origin, options.trustedOrigins, context.logger);
3399
+ context.origin = origin;
3400
+ context.trustedOrigin = trusted;
3401
+ }
3402
+ return context;
3403
+ };
3404
+ const processTelemetry = (request, context)=>{
3405
+ const url = new URL(request.url);
3406
+ const path = url.pathname;
3407
+ const method = request.method;
3408
+ withRequestSpan(method, path, async ()=>{}, options);
3409
+ context.path = path;
3410
+ context.method = method;
3411
+ context.headers = request.headers;
3412
+ context.userAgent = request.headers.get('user-agent') || void 0;
3413
+ return context;
3414
+ };
3415
+ const getOpenAPISpec = async ()=>{
3416
+ if (getOpenAPISpec.cached) return getOpenAPISpec.cached;
3417
+ const mergedOptions = {
3418
+ ...defaultOpenApiOptions
3419
+ };
3420
+ if (openApiConfig.options) {
3421
+ const userOptions = openApiConfig.options;
3422
+ if (userOptions.info) mergedOptions.info = {
3423
+ ...defaultOpenApiOptions.info,
3424
+ ...userOptions.info
3425
+ };
3426
+ for (const [key, value] of Object.entries(userOptions))if ('info' !== key) mergedOptions[key] = value;
3427
+ }
3428
+ const spec = await openAPIGenerator.generate(router, mergedOptions);
3429
+ getOpenAPISpec.cached = spec;
3430
+ return spec;
3431
+ };
3432
+ const getDocsUI = ()=>{
3433
+ if (openApiConfig.customUiTemplate) return openApiConfig.customUiTemplate;
3434
+ return `
3435
+ <!doctype html>
3436
+ <html>
3437
+ <head>
3438
+ <title>${options.appName || 'c15t API'} Documentation</title>
3439
+ <meta charset="utf-8" />
3440
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
3441
+ <link rel="icon" type="image/svg+xml" href="https://orpc.unnoq.com/icon.svg" />
3442
+ </head>
3443
+ <body>
3444
+ <script
3445
+ id="api-reference"
3446
+ data-url="${encodeURI(openApiConfig.specPath)}">
3447
+ </script>
3448
+ <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
3449
+ </body>
3450
+ </html>
3451
+ `;
3452
+ };
3453
+ const handleOpenApiSpecRequest = async (url)=>{
3454
+ if (openApiConfig.enabled && url.pathname === openApiConfig.specPath) {
3455
+ const spec = await getOpenAPISpec();
3456
+ return new Response(JSON.stringify(spec), {
3457
+ status: 200,
3458
+ headers: {
3459
+ 'Content-Type': 'application/json'
3460
+ }
3461
+ });
3462
+ }
3463
+ return null;
3464
+ };
3465
+ const handleDocsUiRequest = (url)=>{
3466
+ if (openApiConfig.enabled && url.pathname === openApiConfig.docsPath) {
3467
+ const html = getDocsUI();
3468
+ return new Response(html, {
3469
+ status: 200,
3470
+ headers: {
3471
+ 'Content-Type': 'text/html',
3472
+ 'Content-Security-Policy': "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net;"
3473
+ }
3474
+ });
3475
+ }
3476
+ return null;
3477
+ };
3478
+ const createDoubleTieErrorResponse = (error)=>{
3479
+ const sanitizedMessage = error.message.replace(/[^\w\s.,;:!?()[\]{}'"+-]/g, '');
3480
+ return new Response(JSON.stringify({
3481
+ code: error.code,
3482
+ message: sanitizedMessage,
3483
+ data: error.meta,
3484
+ status: error.statusCode,
3485
+ defined: true
3486
+ }), {
3487
+ status: error.statusCode,
3488
+ headers: {
3489
+ 'Content-Type': 'application/json'
3490
+ }
3491
+ });
3492
+ };
3493
+ const createUnknownErrorResponse = (error)=>{
3494
+ const message = error instanceof Error ? error.message : String(error);
3495
+ let status = 500;
3496
+ if (error instanceof Error && 'status' in error) {
3497
+ const statusValue = error.status;
3498
+ if ('number' == typeof statusValue && statusValue >= 100 && statusValue < 600) status = statusValue;
3499
+ }
3500
+ return new Response(JSON.stringify({
3501
+ code: error_codes_ERROR_CODES.INTERNAL_SERVER_ERROR,
3502
+ message,
3503
+ status,
3504
+ defined: true,
3505
+ data: {}
3506
+ }), {
3507
+ status,
3508
+ headers: {
3509
+ 'Content-Type': 'application/json'
3510
+ }
3511
+ });
3512
+ };
3513
+ const handleApiRequest = async (request, ctx)=>{
3514
+ const orpcContext = {
3515
+ adapter: ctx.adapter,
3516
+ registry: ctx.registry,
3517
+ logger: ctx.logger,
3518
+ generateId: ctx.generateId,
3519
+ headers: request.headers,
3520
+ userAgent: request.headers.get('user-agent') || void 0
3521
+ };
3522
+ processIp(request, orpcContext);
3523
+ processCors(request, orpcContext);
3524
+ processTelemetry(request, orpcContext);
3525
+ const handlerContext = orpcContext;
3526
+ const { matched, response } = await rpcHandler.handle(request, {
3527
+ prefix: '/',
3528
+ context: handlerContext
3529
+ });
3530
+ if (matched && response) return response;
3531
+ return new Response('Not Found', {
3532
+ status: 404
3533
+ });
3534
+ };
3535
+ const handler = async (request)=>{
3536
+ try {
3537
+ const url = new URL(request.url);
3538
+ const openApiResponse = await handleOpenApiSpecRequest(url);
3539
+ if (openApiResponse) return openApiResponse;
3540
+ const docsResponse = handleDocsUiRequest(url);
3541
+ if (docsResponse) return docsResponse;
3542
+ const ctxResult = await contextPromise;
3543
+ if (!ctxResult.isOk()) throw ctxResult.error;
3544
+ const ctx = ctxResult.value;
3545
+ return await handleApiRequest(request, ctx);
3546
+ } catch (error) {
3547
+ const logger = options.logger ? (0, logger_namespaceObject.createLogger)(options.logger) : console;
3548
+ logger.error('Request handling error:', error);
3549
+ if (error instanceof error_class_DoubleTieError) return createDoubleTieErrorResponse(error);
3550
+ return createUnknownErrorResponse(error);
3551
+ }
3552
+ };
3553
+ const createNextHandlers = ()=>{
3554
+ const nextHandler = async (request)=>await handler(request);
3555
+ return {
3556
+ GET: nextHandler,
3557
+ POST: nextHandler,
3558
+ PUT: nextHandler,
3559
+ PATCH: nextHandler,
3560
+ DELETE: nextHandler,
3561
+ OPTIONS: nextHandler,
3562
+ HEAD: nextHandler
3563
+ };
3564
+ };
3565
+ return {
3566
+ options,
3567
+ $context: contextPromise.then((result)=>{
3568
+ if (!result.isOk()) throw result.error;
3569
+ return result.value;
3570
+ }),
3571
+ router: router,
3572
+ handler,
3573
+ ...createNextHandlers(),
3574
+ getOpenAPISpec,
3575
+ getDocsUI
3576
+ };
3577
+ };
3578
+ exports.c15tInstance = __webpack_exports__.c15tInstance;
3579
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
3580
+ "c15tInstance"
3581
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
3582
+ Object.defineProperty(exports, '__esModule', {
3583
+ value: true
3584
+ });