@c15t/backend 2.0.0-rc.0 → 2.0.0-rc.10

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 (336) hide show
  1. package/README.md +3 -3
  2. package/dist/302.js +473 -0
  3. package/dist/583.js +540 -0
  4. package/dist/915.js +1771 -0
  5. package/dist/cache.cjs +5 -5
  6. package/dist/cache.js +4 -415
  7. package/dist/core.cjs +1356 -120
  8. package/dist/core.js +163 -1981
  9. package/dist/db/adapters/drizzle.cjs +1 -1
  10. package/dist/db/adapters/drizzle.js +1 -2
  11. package/dist/db/adapters/kysely.cjs +1 -1
  12. package/dist/db/adapters/kysely.js +1 -2
  13. package/dist/db/adapters/mongo.cjs +1 -1
  14. package/dist/db/adapters/mongo.js +1 -2
  15. package/dist/db/adapters/prisma.cjs +1 -1
  16. package/dist/db/adapters/prisma.js +1 -2
  17. package/dist/db/adapters/typeorm.cjs +1 -1
  18. package/dist/db/adapters/typeorm.js +1 -2
  19. package/dist/db/adapters.cjs +1 -1
  20. package/dist/db/migrator.cjs +1 -1
  21. package/dist/db/schema.cjs +43 -3
  22. package/dist/db/schema.js +35 -4
  23. package/dist/define-config.cjs +1 -1
  24. package/dist/edge.cjs +1106 -0
  25. package/dist/edge.js +190 -0
  26. package/dist/router.cjs +885 -123
  27. package/dist/router.js +1 -1507
  28. package/dist/{types.cjs → types/index.cjs} +1 -1
  29. package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
  30. package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
  31. package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
  32. package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
  33. package/{dist → dist-types}/cache/gvl-resolver.d.ts +0 -1
  34. package/{dist → dist-types}/cache/index.d.ts +0 -1
  35. package/{dist → dist-types}/cache/keys.d.ts +0 -1
  36. package/{dist → dist-types}/cache/types.d.ts +0 -1
  37. package/{dist → dist-types}/core.d.ts +8 -1
  38. package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
  39. package/dist-types/db/registry/consent-policy.d.ts +78 -0
  40. package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
  41. package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
  42. package/dist-types/db/registry/index.d.ts +118 -0
  43. package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
  44. package/{dist → dist-types}/db/registry/subject.d.ts +0 -2
  45. package/{dist → dist-types}/db/registry/types.d.ts +1 -1
  46. package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
  47. package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
  48. package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
  49. package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
  50. package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
  51. package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
  52. package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
  53. package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
  54. package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -32
  55. package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -2
  56. package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
  57. package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +3 -3
  58. package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
  59. package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +7 -2
  60. package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
  61. package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +455 -28
  62. package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
  63. package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -3
  64. package/{dist → dist-types}/db/schema/index.d.ts +908 -86
  65. package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
  66. package/dist-types/define-config.d.ts +17 -0
  67. package/dist-types/edge/index.d.ts +5 -0
  68. package/dist-types/edge/init-handler.d.ts +40 -0
  69. package/dist-types/edge/resolve-consent.d.ts +80 -0
  70. package/dist-types/edge/types.d.ts +13 -0
  71. package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
  72. package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
  73. package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
  74. package/{dist → dist-types}/handlers/init/index.d.ts +2 -3
  75. package/dist-types/handlers/init/policy.d.ts +26 -0
  76. package/dist-types/handlers/init/resolve-init.d.ts +44 -0
  77. package/dist-types/handlers/init/translations.d.ts +48 -0
  78. package/dist-types/handlers/legal-document/current.handler.d.ts +11 -0
  79. package/dist-types/handlers/legal-document/snapshot.d.ts +39 -0
  80. package/dist-types/handlers/policy/snapshot.d.ts +99 -0
  81. package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
  82. package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
  83. package/{dist → dist-types}/handlers/subject/get.handler.d.ts +3 -2
  84. package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
  85. package/{dist → dist-types}/handlers/subject/list.handler.d.ts +3 -2
  86. package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -2
  87. package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
  88. package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +3 -1
  89. package/{dist → dist-types}/init.d.ts +4 -7
  90. package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
  91. package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
  92. package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
  93. package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
  94. package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +0 -1
  95. package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
  96. package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
  97. package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
  98. package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
  99. package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
  100. package/dist-types/policies/builder.d.ts +127 -0
  101. package/dist-types/policies/defaults.d.ts +2 -0
  102. package/dist-types/policies/matchers.d.ts +3 -0
  103. package/{dist → dist-types}/router.d.ts +0 -1
  104. package/{dist → dist-types}/routes/consent.d.ts +0 -1
  105. package/{dist → dist-types}/routes/index.d.ts +1 -1
  106. package/{dist → dist-types}/routes/init.d.ts +0 -1
  107. package/dist-types/routes/legal-document.d.ts +7 -0
  108. package/{dist → dist-types}/routes/status.d.ts +0 -1
  109. package/{dist → dist-types}/routes/subject.d.ts +0 -1
  110. package/{dist → dist-types}/types/api.d.ts +0 -1
  111. package/dist-types/types/index.d.ts +464 -0
  112. package/dist-types/utils/background.d.ts +6 -0
  113. package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
  114. package/{dist → dist-types}/utils/env.d.ts +0 -1
  115. package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
  116. package/{dist → dist-types}/utils/instrumentation.d.ts +2 -3
  117. package/{dist → dist-types}/utils/logger.d.ts +0 -1
  118. package/{dist → dist-types}/utils/metrics.d.ts +0 -1
  119. package/dist-types/version.d.ts +1 -0
  120. package/docs/README.md +49 -0
  121. package/docs/api/configuration.md +208 -0
  122. package/docs/api/endpoints.md +211 -0
  123. package/docs/guides/caching.md +85 -0
  124. package/docs/guides/database-setup.md +128 -0
  125. package/docs/guides/edge-deployment.md +251 -0
  126. package/docs/guides/framework-integration.md +142 -0
  127. package/docs/guides/iab-tcf.md +89 -0
  128. package/docs/guides/observability.md +96 -0
  129. package/docs/guides/policy-packs.md +396 -0
  130. package/docs/quickstart.md +129 -0
  131. package/package.json +53 -39
  132. package/.turbo/turbo-build.log +0 -49
  133. package/CHANGELOG.md +0 -89
  134. package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
  135. package/dist/cache/adapters/index.d.ts.map +0 -1
  136. package/dist/cache/adapters/memory.d.ts.map +0 -1
  137. package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
  138. package/dist/cache/gvl-resolver.d.ts.map +0 -1
  139. package/dist/cache/index.d.ts.map +0 -1
  140. package/dist/cache/keys.d.ts.map +0 -1
  141. package/dist/cache/types.d.ts.map +0 -1
  142. package/dist/core.d.ts.map +0 -1
  143. package/dist/db/adapters/drizzle.d.ts +0 -2
  144. package/dist/db/adapters/drizzle.d.ts.map +0 -1
  145. package/dist/db/adapters/index.d.ts +0 -2
  146. package/dist/db/adapters/index.d.ts.map +0 -1
  147. package/dist/db/adapters/kysely.d.ts +0 -2
  148. package/dist/db/adapters/kysely.d.ts.map +0 -1
  149. package/dist/db/adapters/mongo.d.ts +0 -2
  150. package/dist/db/adapters/mongo.d.ts.map +0 -1
  151. package/dist/db/adapters/prisma.d.ts +0 -2
  152. package/dist/db/adapters/prisma.d.ts.map +0 -1
  153. package/dist/db/adapters/typeorm.d.ts +0 -2
  154. package/dist/db/adapters/typeorm.d.ts.map +0 -1
  155. package/dist/db/migrator/index.d.ts.map +0 -1
  156. package/dist/db/registry/consent-policy.d.ts +0 -23
  157. package/dist/db/registry/consent-policy.d.ts.map +0 -1
  158. package/dist/db/registry/consent-purpose.d.ts.map +0 -1
  159. package/dist/db/registry/domain.d.ts.map +0 -1
  160. package/dist/db/registry/index.d.ts +0 -57
  161. package/dist/db/registry/index.d.ts.map +0 -1
  162. package/dist/db/registry/subject.d.ts.map +0 -1
  163. package/dist/db/registry/types.d.ts.map +0 -1
  164. package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
  165. package/dist/db/registry/utils.d.ts.map +0 -1
  166. package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
  167. package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
  168. package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
  169. package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
  170. package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
  171. package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
  172. package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
  173. package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
  174. package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
  175. package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
  176. package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
  177. package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
  178. package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
  179. package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
  180. package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
  181. package/dist/db/schema/index.d.ts.map +0 -1
  182. package/dist/db/tenant-scope.d.ts.map +0 -1
  183. package/dist/define-config.d.ts +0 -5
  184. package/dist/define-config.d.ts.map +0 -1
  185. package/dist/handlers/consent/check.handler.d.ts.map +0 -1
  186. package/dist/handlers/consent/index.d.ts +0 -12
  187. package/dist/handlers/consent/index.d.ts.map +0 -1
  188. package/dist/handlers/init/geo.d.ts.map +0 -1
  189. package/dist/handlers/init/index.d.ts.map +0 -1
  190. package/dist/handlers/init/translations.d.ts +0 -28
  191. package/dist/handlers/init/translations.d.ts.map +0 -1
  192. package/dist/handlers/status/index.d.ts +0 -7
  193. package/dist/handlers/status/index.d.ts.map +0 -1
  194. package/dist/handlers/status/status.handler.d.ts.map +0 -1
  195. package/dist/handlers/subject/get.handler.d.ts.map +0 -1
  196. package/dist/handlers/subject/index.d.ts +0 -10
  197. package/dist/handlers/subject/index.d.ts.map +0 -1
  198. package/dist/handlers/subject/list.handler.d.ts.map +0 -1
  199. package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
  200. package/dist/handlers/subject/post.handler.d.ts.map +0 -1
  201. package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
  202. package/dist/init.d.ts.map +0 -1
  203. package/dist/middleware/auth/index.d.ts.map +0 -1
  204. package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
  205. package/dist/middleware/cors/cors.d.ts.map +0 -1
  206. package/dist/middleware/cors/index.d.ts +0 -30
  207. package/dist/middleware/cors/index.d.ts.map +0 -1
  208. package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
  209. package/dist/middleware/cors/process-cors.d.ts.map +0 -1
  210. package/dist/middleware/openapi/config.d.ts.map +0 -1
  211. package/dist/middleware/openapi/handlers.d.ts.map +0 -1
  212. package/dist/middleware/openapi/index.d.ts +0 -12
  213. package/dist/middleware/openapi/index.d.ts.map +0 -1
  214. package/dist/middleware/process-ip/index.d.ts.map +0 -1
  215. package/dist/router.d.ts.map +0 -1
  216. package/dist/routes/consent.d.ts.map +0 -1
  217. package/dist/routes/index.d.ts.map +0 -1
  218. package/dist/routes/init.d.ts.map +0 -1
  219. package/dist/routes/status.d.ts.map +0 -1
  220. package/dist/routes/subject.d.ts.map +0 -1
  221. package/dist/types/api.d.ts.map +0 -1
  222. package/dist/types/index.d.ts +0 -255
  223. package/dist/types/index.d.ts.map +0 -1
  224. package/dist/utils/create-telemetry-options.d.ts.map +0 -1
  225. package/dist/utils/env.d.ts.map +0 -1
  226. package/dist/utils/extract-error-message.d.ts.map +0 -1
  227. package/dist/utils/index.d.ts +0 -4
  228. package/dist/utils/index.d.ts.map +0 -1
  229. package/dist/utils/instrumentation.d.ts.map +0 -1
  230. package/dist/utils/logger.d.ts.map +0 -1
  231. package/dist/utils/metrics.d.ts.map +0 -1
  232. package/dist/version.d.ts +0 -2
  233. package/dist/version.d.ts.map +0 -1
  234. package/knip.json +0 -31
  235. package/rslib.config.ts +0 -93
  236. package/src/cache/adapters/cloudflare-kv.ts +0 -71
  237. package/src/cache/adapters/index.ts +0 -22
  238. package/src/cache/adapters/memory.ts +0 -111
  239. package/src/cache/adapters/upstash-redis.ts +0 -113
  240. package/src/cache/gvl-resolver.ts +0 -289
  241. package/src/cache/index.ts +0 -34
  242. package/src/cache/keys.ts +0 -68
  243. package/src/cache/types.ts +0 -66
  244. package/src/core.ts +0 -368
  245. package/src/db/migrator/index.ts +0 -80
  246. package/src/db/registry/consent-policy.test.ts +0 -451
  247. package/src/db/registry/consent-policy.ts +0 -82
  248. package/src/db/registry/consent-purpose.test.ts +0 -428
  249. package/src/db/registry/consent-purpose.ts +0 -61
  250. package/src/db/registry/domain.test.ts +0 -445
  251. package/src/db/registry/domain.ts +0 -91
  252. package/src/db/registry/index.ts +0 -14
  253. package/src/db/registry/subject.test.ts +0 -388
  254. package/src/db/registry/subject.ts +0 -129
  255. package/src/db/registry/types.ts +0 -10
  256. package/src/db/registry/utils/generate-id.test.ts +0 -216
  257. package/src/db/registry/utils/generate-id.ts +0 -133
  258. package/src/db/registry/utils.ts +0 -133
  259. package/src/db/schema/1.0.0/audit-log.ts +0 -15
  260. package/src/db/schema/1.0.0/consent-policy.ts +0 -14
  261. package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
  262. package/src/db/schema/1.0.0/consent-record.ts +0 -10
  263. package/src/db/schema/1.0.0/consent.ts +0 -20
  264. package/src/db/schema/1.0.0/domain.ts +0 -12
  265. package/src/db/schema/1.0.0/index.ts +0 -48
  266. package/src/db/schema/1.0.0/subject.ts +0 -12
  267. package/src/db/schema/2.0.0/audit-log.ts +0 -18
  268. package/src/db/schema/2.0.0/consent-policy.ts +0 -28
  269. package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
  270. package/src/db/schema/2.0.0/consent.ts +0 -26
  271. package/src/db/schema/2.0.0/domain.ts +0 -12
  272. package/src/db/schema/2.0.0/index.ts +0 -47
  273. package/src/db/schema/2.0.0/subject.ts +0 -14
  274. package/src/db/schema/index.ts +0 -15
  275. package/src/db/tenant-scope.test.ts +0 -750
  276. package/src/db/tenant-scope.ts +0 -103
  277. package/src/define-config.ts +0 -5
  278. package/src/handlers/consent/check.handler.ts +0 -126
  279. package/src/handlers/init/geo.test.ts +0 -317
  280. package/src/handlers/init/geo.ts +0 -195
  281. package/src/handlers/init/index.test.ts +0 -205
  282. package/src/handlers/init/index.ts +0 -114
  283. package/src/handlers/init/translations.test.ts +0 -121
  284. package/src/handlers/init/translations.ts +0 -72
  285. package/src/handlers/status/status.handler.test.ts +0 -155
  286. package/src/handlers/status/status.handler.ts +0 -51
  287. package/src/handlers/subject/get.handler.ts +0 -93
  288. package/src/handlers/subject/list.handler.ts +0 -93
  289. package/src/handlers/subject/patch.handler.ts +0 -122
  290. package/src/handlers/subject/post.handler.test.ts +0 -294
  291. package/src/handlers/subject/post.handler.ts +0 -254
  292. package/src/handlers/utils/consent-enrichment.test.ts +0 -380
  293. package/src/handlers/utils/consent-enrichment.ts +0 -218
  294. package/src/init.test.ts +0 -126
  295. package/src/init.ts +0 -87
  296. package/src/middleware/auth/index.ts +0 -11
  297. package/src/middleware/auth/validate-api-key.test.ts +0 -86
  298. package/src/middleware/auth/validate-api-key.ts +0 -107
  299. package/src/middleware/cors/cors.test.ts +0 -135
  300. package/src/middleware/cors/cors.ts +0 -186
  301. package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
  302. package/src/middleware/cors/is-origin-trusted.ts +0 -130
  303. package/src/middleware/cors/process-cors.ts +0 -91
  304. package/src/middleware/openapi/config.ts +0 -29
  305. package/src/middleware/openapi/handlers.ts +0 -34
  306. package/src/middleware/process-ip/index.test.ts +0 -195
  307. package/src/middleware/process-ip/index.ts +0 -199
  308. package/src/router.ts +0 -15
  309. package/src/routes/consent.ts +0 -52
  310. package/src/routes/index.ts +0 -10
  311. package/src/routes/init.ts +0 -102
  312. package/src/routes/status.ts +0 -46
  313. package/src/routes/subject.ts +0 -152
  314. package/src/types/api.ts +0 -48
  315. package/src/types/index.ts +0 -288
  316. package/src/utils/create-telemetry-options.test.ts +0 -302
  317. package/src/utils/create-telemetry-options.ts +0 -229
  318. package/src/utils/env.ts +0 -84
  319. package/src/utils/extract-error-message.ts +0 -21
  320. package/src/utils/instrumentation.test.ts +0 -185
  321. package/src/utils/instrumentation.ts +0 -196
  322. package/src/utils/logger.ts +0 -41
  323. package/src/utils/metrics.test.ts +0 -323
  324. package/src/utils/metrics.ts +0 -402
  325. package/src/utils/telemetry-pii.test.ts +0 -325
  326. package/src/version.ts +0 -2
  327. package/tsconfig.json +0 -11
  328. package/vitest.config.ts +0 -28
  329. /package/dist/{types.js → types/index.js} +0 -0
  330. /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
  331. /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
  332. /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
  333. /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
  334. /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
  335. /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
  336. /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
package/src/init.ts DELETED
@@ -1,87 +0,0 @@
1
- import type { C15TContext, C15TOptions } from '~/types';
2
- import { createRegistry } from './db/registry';
3
- import { DB } from './db/schema';
4
- import { withTenantScope } from './db/tenant-scope';
5
- import {
6
- createTelemetryOptions,
7
- isTelemetryEnabled,
8
- } from './utils/create-telemetry-options';
9
- import { initLogger } from './utils/logger';
10
-
11
- /**
12
- * Initializes the c15t backend context.
13
- *
14
- * Telemetry (tracing and metrics) is opt-in and disabled by default.
15
- * Users must:
16
- * 1. Set up their own OpenTelemetry SDK (Node.js, Bun, edge runtime, etc.)
17
- * 2. Pass enabled: true and optionally a tracer/meter to the telemetry config
18
- *
19
- * @example
20
- * ```typescript
21
- * // User sets up their own SDK before calling init
22
- * import { NodeSDK } from '@opentelemetry/sdk-node';
23
- * const sdk = new NodeSDK({ ... });
24
- * sdk.start();
25
- *
26
- * // Then pass telemetry config
27
- * const instance = c15tInstance({
28
- * advanced: {
29
- * telemetry: {
30
- * enabled: true,
31
- * tracer: trace.getTracer('my-app'),
32
- * meter: metrics.getMeter('my-app'),
33
- * },
34
- * },
35
- * });
36
- * ```
37
- */
38
- export const init = (options: C15TOptions): C15TContext => {
39
- const appName = options.appName || 'c15t';
40
-
41
- const logger = initLogger({
42
- ...options.logger,
43
- appName: String(appName),
44
- });
45
-
46
- // Create telemetry options (validates and merges with defaults)
47
- const telemetryOptions = createTelemetryOptions(
48
- String(appName),
49
- options.advanced?.telemetry,
50
- options.tenantId
51
- );
52
-
53
- // Log telemetry status
54
- if (isTelemetryEnabled(options)) {
55
- logger.debug('Telemetry is enabled', {
56
- hasTracer: !!telemetryOptions?.tracer,
57
- hasMeter: !!telemetryOptions?.meter,
58
- attributes: telemetryOptions?.defaultAttributes,
59
- });
60
- } else {
61
- logger.debug('Telemetry is disabled (opt-in required)');
62
- }
63
-
64
- // Initialize core components
65
- const db = options.tablePrefix ? DB.names.prefix(options.tablePrefix) : DB;
66
- const client = db.client(options.adapter);
67
-
68
- const rawOrm = client.orm('2.0.0');
69
- const orm = options.tenantId
70
- ? withTenantScope(rawOrm, options.tenantId)
71
- : rawOrm;
72
-
73
- const context: C15TContext = {
74
- ...options,
75
- appName,
76
- logger,
77
- db: orm,
78
- registry: createRegistry({
79
- db: orm,
80
- ctx: {
81
- logger,
82
- },
83
- }),
84
- };
85
-
86
- return context;
87
- };
@@ -1,11 +0,0 @@
1
- /**
2
- * Authentication middleware exports.
3
- *
4
- * @packageDocumentation
5
- */
6
-
7
- export {
8
- extractBearerToken,
9
- validateApiKey,
10
- validateRequestAuth,
11
- } from './validate-api-key';
@@ -1,86 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import {
3
- extractBearerToken,
4
- validateApiKey,
5
- validateRequestAuth,
6
- } from './validate-api-key';
7
-
8
- describe('extractBearerToken', () => {
9
- it('should extract token from valid Bearer header', () => {
10
- expect(extractBearerToken('Bearer sk_live_abc123')).toBe('sk_live_abc123');
11
- });
12
-
13
- it('should return null for non-Bearer auth', () => {
14
- expect(extractBearerToken('Basic abc123')).toBeNull();
15
- });
16
-
17
- it('should return null for missing Bearer prefix', () => {
18
- expect(extractBearerToken('sk_live_abc123')).toBeNull();
19
- });
20
-
21
- it('should return null for null header', () => {
22
- expect(extractBearerToken(null)).toBeNull();
23
- });
24
-
25
- it('should return null for empty header', () => {
26
- expect(extractBearerToken('')).toBeNull();
27
- });
28
-
29
- it('should handle extra spaces', () => {
30
- expect(extractBearerToken('Bearer abc123')).toBeNull(); // Two spaces
31
- });
32
- });
33
-
34
- describe('validateApiKey', () => {
35
- const validKeys = ['sk_live_abc123', 'sk_live_def456'];
36
-
37
- it('should return true for valid key', () => {
38
- expect(validateApiKey('sk_live_abc123', validKeys)).toBe(true);
39
- expect(validateApiKey('sk_live_def456', validKeys)).toBe(true);
40
- });
41
-
42
- it('should return false for invalid key', () => {
43
- expect(validateApiKey('sk_live_invalid', validKeys)).toBe(false);
44
- });
45
-
46
- it('should return false for null token', () => {
47
- expect(validateApiKey(null, validKeys)).toBe(false);
48
- });
49
-
50
- it('should return false for undefined keys', () => {
51
- expect(validateApiKey('sk_live_abc123', undefined)).toBe(false);
52
- });
53
-
54
- it('should return false for empty keys array', () => {
55
- expect(validateApiKey('sk_live_abc123', [])).toBe(false);
56
- });
57
-
58
- it('should be case-sensitive', () => {
59
- expect(validateApiKey('SK_LIVE_ABC123', validKeys)).toBe(false);
60
- });
61
- });
62
-
63
- describe('validateRequestAuth', () => {
64
- const validKeys = ['sk_live_abc123'];
65
-
66
- it('should return true for valid Authorization header', () => {
67
- const headers = new Headers();
68
- headers.set('Authorization', 'Bearer sk_live_abc123');
69
- expect(validateRequestAuth(headers, validKeys)).toBe(true);
70
- });
71
-
72
- it('should return false for invalid token', () => {
73
- const headers = new Headers();
74
- headers.set('Authorization', 'Bearer sk_live_invalid');
75
- expect(validateRequestAuth(headers, validKeys)).toBe(false);
76
- });
77
-
78
- it('should return false for missing Authorization header', () => {
79
- const headers = new Headers();
80
- expect(validateRequestAuth(headers, validKeys)).toBe(false);
81
- });
82
-
83
- it('should return false for undefined headers', () => {
84
- expect(validateRequestAuth(undefined, validKeys)).toBe(false);
85
- });
86
- });
@@ -1,107 +0,0 @@
1
- /**
2
- * API key validation utilities.
3
- *
4
- * @packageDocumentation
5
- */
6
-
7
- /**
8
- * Extracts the Bearer token from an Authorization header.
9
- *
10
- * @param authHeader - The Authorization header value
11
- * @returns The token if valid Bearer format, null otherwise
12
- *
13
- * @example
14
- * ```typescript
15
- * extractBearerToken('Bearer sk_live_abc123'); // 'sk_live_abc123'
16
- * extractBearerToken('Basic abc123'); // null
17
- * extractBearerToken('sk_live_abc123'); // null
18
- * ```
19
- */
20
- export function extractBearerToken(authHeader: string | null): string | null {
21
- if (!authHeader) {
22
- return null;
23
- }
24
-
25
- const parts = authHeader.split(' ');
26
- if (parts.length !== 2 || parts[0] !== 'Bearer') {
27
- return null;
28
- }
29
-
30
- return parts[1] || null;
31
- }
32
-
33
- /**
34
- * Validates an API key against the configured keys.
35
- *
36
- * @param token - The token to validate
37
- * @param validKeys - Array of valid API keys
38
- * @returns True if the token is valid
39
- *
40
- * @remarks
41
- * Uses timing-safe comparison to prevent timing attacks.
42
- * If no keys are configured, returns false.
43
- */
44
- export function validateApiKey(
45
- token: string | null,
46
- validKeys: string[] | undefined
47
- ): boolean {
48
- if (!token || !validKeys || validKeys.length === 0) {
49
- return false;
50
- }
51
-
52
- // Use timing-safe comparison to prevent timing attacks
53
- return validKeys.some((key) => timingSafeEqual(token, key));
54
- }
55
-
56
- /**
57
- * Timing-safe string comparison to prevent timing attacks.
58
- *
59
- * @param a - First string
60
- * @param b - Second string
61
- * @returns True if strings are equal
62
- */
63
- function timingSafeEqual(a: string, b: string): boolean {
64
- if (a.length !== b.length) {
65
- // Still do comparison to maintain constant time
66
- let result = 0;
67
- for (let i = 0; i < a.length; i++) {
68
- result |= a.charCodeAt(i) ^ (b.charCodeAt(i % b.length) || 0);
69
- }
70
- return false;
71
- }
72
-
73
- let result = 0;
74
- for (let i = 0; i < a.length; i++) {
75
- result |= a.charCodeAt(i) ^ b.charCodeAt(i);
76
- }
77
- return result === 0;
78
- }
79
-
80
- /**
81
- * Validates authentication from request headers.
82
- *
83
- * @param headers - Request headers
84
- * @param validKeys - Array of valid API keys
85
- * @returns True if the request has a valid API key
86
- *
87
- * @example
88
- * ```typescript
89
- * const headers = new Headers();
90
- * headers.set('Authorization', 'Bearer sk_live_abc123');
91
- *
92
- * validateRequestAuth(headers, ['sk_live_abc123']); // true
93
- * validateRequestAuth(headers, ['sk_live_other']); // false
94
- * ```
95
- */
96
- export function validateRequestAuth(
97
- headers: Headers | undefined,
98
- validKeys: string[] | undefined
99
- ): boolean {
100
- if (!headers) {
101
- return false;
102
- }
103
-
104
- const authHeader = headers.get('Authorization');
105
- const token = extractBearerToken(authHeader);
106
- return validateApiKey(token, validKeys);
107
- }
@@ -1,135 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { createCORSOptions } from './cors';
3
-
4
- /**
5
- * Helper to call the origin function or return a default value
6
- */
7
- const callOrigin = async (
8
- origin: string | string[] | ((origin: string) => string | null) | undefined,
9
- value: string
10
- ): Promise<string | null> => {
11
- if (typeof origin === 'function') {
12
- return origin(value);
13
- }
14
- if (origin === '*') {
15
- return value || '*';
16
- }
17
- if (Array.isArray(origin)) {
18
- return origin.includes(value) ? value : null;
19
- }
20
- return origin === value ? value : null;
21
- };
22
-
23
- describe('createCORSOptions (unit)', () => {
24
- describe('configuration shape', () => {
25
- it('returns expected defaults when no trustedOrigins provided', async () => {
26
- const config = createCORSOptions();
27
- expect(config.credentials).toBe(true);
28
- expect(config.maxAge).toBe(600);
29
- expect(config.allowHeaders).toEqual([
30
- 'Content-Type',
31
- 'Authorization',
32
- 'x-request-id',
33
- 'x-c15t-country',
34
- 'x-c15t-region',
35
- 'accept-language',
36
- ]);
37
- expect(config.methods).toEqual([
38
- 'GET',
39
- 'POST',
40
- 'PUT',
41
- 'DELETE',
42
- 'PATCH',
43
- 'OPTIONS',
44
- ]);
45
- // For default config, origin is '*' string
46
- expect(config.origin).toBe('*');
47
- });
48
- });
49
-
50
- describe('wildcard "*"', () => {
51
- it('allows any concrete origin and echoes it back', async () => {
52
- const config = createCORSOptions(['*']);
53
- expect(await callOrigin(config.origin, 'http://localhost:3002')).toBe(
54
- 'http://localhost:3002'
55
- );
56
- // missing origin -> '*'
57
- expect(await callOrigin(config.origin, '')).toBe('*');
58
- });
59
- });
60
-
61
- describe('specific origins', () => {
62
- it('allows trusted origin and rejects untrusted', async () => {
63
- const config = createCORSOptions(['http://localhost:3002']);
64
- expect(await callOrigin(config.origin, 'http://localhost:3002')).toBe(
65
- 'http://localhost:3002'
66
- );
67
- expect(
68
- await callOrigin(config.origin, 'http://malicious-site.com')
69
- ).toBeNull();
70
- });
71
-
72
- it('treats localhost variants (ports, IPs) as trusted when "localhost" provided', async () => {
73
- const config = createCORSOptions(['localhost']);
74
- expect(await callOrigin(config.origin, 'http://localhost:1234')).toBe(
75
- 'http://localhost:1234'
76
- );
77
- expect(await callOrigin(config.origin, 'http://127.0.0.1:3000')).toBe(
78
- 'http://127.0.0.1:3000'
79
- );
80
- expect(await callOrigin(config.origin, 'http://[::1]:3000')).toBe(
81
- 'http://[::1]:3000'
82
- );
83
- });
84
- });
85
-
86
- describe('www and non-www variants', () => {
87
- it('allows www when non-www is trusted', async () => {
88
- const config = createCORSOptions(['http://c15t.com']);
89
- expect(await callOrigin(config.origin, 'http://www.c15t.com')).toBe(
90
- 'http://www.c15t.com'
91
- );
92
- });
93
-
94
- it('allows non-www when www is trusted', async () => {
95
- const config = createCORSOptions(['http://www.c15t.com']);
96
- expect(await callOrigin(config.origin, 'http://c15t.com')).toBe(
97
- 'http://c15t.com'
98
- );
99
- });
100
- });
101
-
102
- describe('ports and protocols', () => {
103
- it('matches with exact port when provided', async () => {
104
- const config = createCORSOptions(['localhost:3002']);
105
- expect(await callOrigin(config.origin, 'http://localhost:3002')).toBe(
106
- 'http://localhost:3002'
107
- );
108
- expect(
109
- await callOrigin(config.origin, 'http://localhost:4000')
110
- ).toBeNull();
111
- });
112
-
113
- it('is protocol-agnostic for host comparison', async () => {
114
- const config = createCORSOptions(['example.com']);
115
- expect(await callOrigin(config.origin, 'http://example.com')).toBe(
116
- 'http://example.com'
117
- );
118
- expect(await callOrigin(config.origin, 'https://www.example.com')).toBe(
119
- 'https://www.example.com'
120
- );
121
- });
122
- });
123
-
124
- describe('invalid or missing origins', () => {
125
- it('returns null for clearly invalid origins', async () => {
126
- const config = createCORSOptions(['example.com']);
127
- expect(await callOrigin(config.origin, '::::invalid::::')).toBeNull();
128
- });
129
-
130
- it('returns "*" when origin header is missing/empty', async () => {
131
- const config = createCORSOptions(['*']);
132
- expect(await callOrigin(config.origin, '')).toBe('*');
133
- });
134
- });
135
- });
@@ -1,186 +0,0 @@
1
- /**
2
- * CORS middleware utility for c15t that handles origin validation and CORS headers
3
- *
4
- * @packageDocumentation
5
- */
6
-
7
- /**
8
- * CORS configuration options compatible with Hono's cors middleware
9
- */
10
- export interface CorsOptions {
11
- origin: string | string[] | ((origin: string) => string | null);
12
- methods?: string[];
13
- allowMethods?: string[];
14
- allowHeaders?: string[];
15
- maxAge?: number;
16
- credentials?: boolean;
17
- exposeHeaders?: string[];
18
- }
19
-
20
- /** Regular expression to match www prefix in domain names */
21
- const WWW_REGEX = /^www\./;
22
-
23
- /** Regular expression to match protocol and www prefix in URLs */
24
- const PROTOCOL_WWW_REGEX = /^https?:\/\/(www\.)?/;
25
-
26
- /**
27
- * Supported HTTP methods for CORS
28
- */
29
- const SUPPORTED_METHODS = [
30
- 'GET',
31
- 'POST',
32
- 'PUT',
33
- 'DELETE',
34
- 'PATCH',
35
- 'OPTIONS',
36
- ] as const;
37
-
38
- /**
39
- * Supported headers for CORS requests
40
- */
41
- const SUPPORTED_HEADERS = [
42
- 'Content-Type',
43
- 'Authorization',
44
- 'x-request-id',
45
- 'x-c15t-country',
46
- 'x-c15t-region',
47
- 'accept-language',
48
- ] as const;
49
-
50
- /**
51
- * Normalizes an origin string by removing protocol and www prefix
52
- *
53
- * @param origin - The origin URL to normalize
54
- * @returns Normalized origin string without protocol and www prefix
55
- */
56
- function normalizeOrigin(origin: string): string {
57
- try {
58
- // Handle bare domains like 'localhost' or 'example.com'
59
- if (
60
- !origin.includes('://') &&
61
- !origin.includes(':') &&
62
- !origin.includes('/')
63
- ) {
64
- return origin.toLowerCase();
65
- }
66
- // Add protocol if missing
67
- const originWithProtocol =
68
- origin.startsWith('http://') ||
69
- origin.startsWith('https://') ||
70
- origin.startsWith('ws://') ||
71
- origin.startsWith('wss://')
72
- ? origin
73
- : `http://${origin}`;
74
- const url = new URL(originWithProtocol);
75
- const hostname = url.hostname.replace(WWW_REGEX, '');
76
- // Return without protocol to match both http and https
77
- return `${hostname}${url.port ? `:${url.port}` : ''}`;
78
- } catch {
79
- // Fallback: remove www manually and protocol
80
- return origin.replace(PROTOCOL_WWW_REGEX, '').replace(WWW_REGEX, '');
81
- }
82
- }
83
-
84
- /**
85
- * Expands a list of origins to include www variants
86
- *
87
- * @param origins - Array of origin strings to expand
88
- * @returns Array of origins including www variants
89
- */
90
- function expandWithWWW(origins: string[]): string[] {
91
- const expanded = new Set<string>();
92
- for (const origin of origins) {
93
- if (origin === '*') {
94
- expanded.add('*');
95
- continue;
96
- }
97
- const normalized = normalizeOrigin(origin);
98
- expanded.add(normalized);
99
- // Add www version if not already present
100
- if (!normalized.includes('www.')) {
101
- expanded.add(`www.${normalized}`);
102
- }
103
- }
104
- return Array.from(expanded);
105
- }
106
-
107
- /**
108
- * Creates CORS options configuration for Hono's cors middleware
109
- *
110
- * @param trustedOrigins - Array of allowed origin patterns or single string. Can include wildcards ('*').
111
- * If undefined, defaults to allowing all origins without credentials.
112
- *
113
- * @returns Hono CORS configuration object
114
- *
115
- * @example
116
- * ```ts
117
- * const corsOptions = createCORSOptions(['http://localhost:3000', 'https://example.com']);
118
- * app.use('*', cors(corsOptions));
119
- * ```
120
- */
121
- export function createCORSOptions(
122
- trustedOrigins?: string[] | string
123
- ): CorsOptions {
124
- // If trustedOrigins is undefined or empty, return default config that allows all origins
125
- if (!trustedOrigins) {
126
- return {
127
- origin: '*',
128
- credentials: true,
129
- allowHeaders: [...SUPPORTED_HEADERS],
130
- maxAge: 600,
131
- allowMethods: [...SUPPORTED_METHODS],
132
- methods: [...SUPPORTED_METHODS],
133
- };
134
- }
135
-
136
- // Convert string to array if needed
137
- const origins = Array.isArray(trustedOrigins)
138
- ? trustedOrigins
139
- : [trustedOrigins];
140
- if (origins.length === 0) {
141
- return {
142
- origin: '*',
143
- credentials: true,
144
- allowHeaders: [...SUPPORTED_HEADERS],
145
- maxAge: 600,
146
- allowMethods: [...SUPPORTED_METHODS],
147
- methods: [...SUPPORTED_METHODS],
148
- };
149
- }
150
-
151
- const expandedTrusted = expandWithWWW(origins);
152
-
153
- return {
154
- origin: (origin) => {
155
- if (!origin) {
156
- return '*';
157
- }
158
- const normalizedOrigin = normalizeOrigin(origin);
159
- if (expandedTrusted.includes('*')) {
160
- return origin;
161
- }
162
- // Check if the origin matches any trusted origin
163
- const isTrusted = expandedTrusted.some((trusted) => {
164
- const normalizedTrusted = normalizeOrigin(trusted);
165
- // For localhost, match both with and without port
166
- if (normalizedTrusted === 'localhost') {
167
- return (
168
- normalizedOrigin === 'localhost' ||
169
- normalizedOrigin.startsWith('localhost:') ||
170
- normalizedOrigin === '127.0.0.1' ||
171
- normalizedOrigin.startsWith('127.0.0.1:') ||
172
- normalizedOrigin === '[::1]' ||
173
- normalizedOrigin.startsWith('[::1]:')
174
- );
175
- }
176
- return normalizedTrusted === normalizedOrigin;
177
- });
178
- return isTrusted ? origin : null;
179
- },
180
- credentials: true,
181
- allowHeaders: [...SUPPORTED_HEADERS],
182
- maxAge: 600,
183
- allowMethods: [...SUPPORTED_METHODS],
184
- methods: [...SUPPORTED_METHODS],
185
- };
186
- }