@c15t/backend 2.0.0-rc.3 → 2.0.0-rc.5

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 (314) hide show
  1. package/dist/cache.cjs +4 -4
  2. package/dist/cache.js +4 -4
  3. package/dist/core.cjs +845 -87
  4. package/dist/core.js +821 -87
  5. package/dist/db/schema.cjs +37 -0
  6. package/dist/db/schema.js +33 -2
  7. package/dist/edge.cjs +1106 -0
  8. package/dist/edge.js +1069 -0
  9. package/dist/router.cjs +621 -71
  10. package/dist/router.js +621 -71
  11. package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
  12. package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
  13. package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
  14. package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
  15. package/{dist → dist-types}/cache/gvl-resolver.d.ts +1 -2
  16. package/{dist → dist-types}/cache/index.d.ts +0 -1
  17. package/{dist → dist-types}/cache/keys.d.ts +0 -1
  18. package/{dist → dist-types}/cache/types.d.ts +0 -1
  19. package/{dist → dist-types}/core.d.ts +8 -1
  20. package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
  21. package/{dist → dist-types}/db/registry/consent-policy.d.ts +0 -1
  22. package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
  23. package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
  24. package/{dist → dist-types}/db/registry/index.d.ts +22 -2
  25. package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
  26. package/{dist → dist-types}/db/registry/subject.d.ts +0 -1
  27. package/{dist → dist-types}/db/registry/types.d.ts +1 -2
  28. package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
  29. package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
  30. package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
  31. package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
  32. package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
  33. package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
  34. package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
  35. package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
  36. package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -1
  37. package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -1
  38. package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
  39. package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +1 -2
  40. package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
  41. package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +5 -2
  42. package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
  43. package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +432 -17
  44. package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
  45. package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -2
  46. package/{dist → dist-types}/db/schema/index.d.ts +862 -33
  47. package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
  48. package/dist-types/define-config.d.ts +17 -0
  49. package/dist-types/edge/index.d.ts +5 -0
  50. package/dist-types/edge/init-handler.d.ts +38 -0
  51. package/dist-types/edge/resolve-consent.d.ts +80 -0
  52. package/dist-types/edge/types.d.ts +13 -0
  53. package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
  54. package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
  55. package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
  56. package/{dist → dist-types}/handlers/init/index.d.ts +4 -5
  57. package/dist-types/handlers/init/policy.d.ts +26 -0
  58. package/dist-types/handlers/init/resolve-init.d.ts +44 -0
  59. package/dist-types/handlers/init/translations.d.ts +48 -0
  60. package/dist-types/handlers/policy/snapshot.d.ts +99 -0
  61. package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
  62. package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
  63. package/{dist → dist-types}/handlers/subject/get.handler.d.ts +0 -1
  64. package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
  65. package/{dist → dist-types}/handlers/subject/list.handler.d.ts +0 -1
  66. package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -1
  67. package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
  68. package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +0 -1
  69. package/{dist → dist-types}/init.d.ts +4 -7
  70. package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
  71. package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
  72. package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
  73. package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
  74. package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +1 -2
  75. package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
  76. package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
  77. package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
  78. package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
  79. package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
  80. package/dist-types/policies/builder.d.ts +127 -0
  81. package/dist-types/policies/defaults.d.ts +2 -0
  82. package/dist-types/policies/matchers.d.ts +3 -0
  83. package/{dist → dist-types}/router.d.ts +0 -1
  84. package/{dist → dist-types}/routes/consent.d.ts +0 -1
  85. package/{src/routes/index.ts → dist-types/routes/index.d.ts} +0 -1
  86. package/{dist → dist-types}/routes/init.d.ts +0 -1
  87. package/{dist → dist-types}/routes/status.d.ts +0 -1
  88. package/{dist → dist-types}/routes/subject.d.ts +0 -1
  89. package/{dist → dist-types}/types/api.d.ts +0 -1
  90. package/dist-types/types/index.d.ts +443 -0
  91. package/dist-types/utils/background.d.ts +6 -0
  92. package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
  93. package/{dist → dist-types}/utils/env.d.ts +0 -1
  94. package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
  95. package/{dist → dist-types}/utils/instrumentation.d.ts +0 -1
  96. package/{dist → dist-types}/utils/logger.d.ts +1 -2
  97. package/{dist → dist-types}/utils/metrics.d.ts +0 -1
  98. package/dist-types/version.d.ts +1 -0
  99. package/docs/README.md +49 -0
  100. package/docs/api/configuration.md +197 -0
  101. package/docs/api/endpoints.md +211 -0
  102. package/docs/guides/caching.md +85 -0
  103. package/docs/guides/database-setup.md +128 -0
  104. package/docs/guides/edge-deployment.md +248 -0
  105. package/docs/guides/framework-integration.md +142 -0
  106. package/docs/guides/iab-tcf.md +89 -0
  107. package/docs/guides/observability.md +96 -0
  108. package/docs/guides/policy-packs.md +396 -0
  109. package/docs/quickstart.md +129 -0
  110. package/package.json +37 -23
  111. package/.turbo/turbo-build.log +0 -49
  112. package/CHANGELOG.md +0 -115
  113. package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
  114. package/dist/cache/adapters/index.d.ts.map +0 -1
  115. package/dist/cache/adapters/memory.d.ts.map +0 -1
  116. package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
  117. package/dist/cache/gvl-resolver.d.ts.map +0 -1
  118. package/dist/cache/index.d.ts.map +0 -1
  119. package/dist/cache/keys.d.ts.map +0 -1
  120. package/dist/cache/types.d.ts.map +0 -1
  121. package/dist/core.d.ts.map +0 -1
  122. package/dist/db/adapters/drizzle.d.ts +0 -2
  123. package/dist/db/adapters/drizzle.d.ts.map +0 -1
  124. package/dist/db/adapters/index.d.ts +0 -2
  125. package/dist/db/adapters/index.d.ts.map +0 -1
  126. package/dist/db/adapters/kysely.d.ts +0 -2
  127. package/dist/db/adapters/kysely.d.ts.map +0 -1
  128. package/dist/db/adapters/mongo.d.ts +0 -2
  129. package/dist/db/adapters/mongo.d.ts.map +0 -1
  130. package/dist/db/adapters/prisma.d.ts +0 -2
  131. package/dist/db/adapters/prisma.d.ts.map +0 -1
  132. package/dist/db/adapters/typeorm.d.ts +0 -2
  133. package/dist/db/adapters/typeorm.d.ts.map +0 -1
  134. package/dist/db/migrator/index.d.ts.map +0 -1
  135. package/dist/db/registry/consent-policy.d.ts.map +0 -1
  136. package/dist/db/registry/consent-purpose.d.ts.map +0 -1
  137. package/dist/db/registry/domain.d.ts.map +0 -1
  138. package/dist/db/registry/index.d.ts.map +0 -1
  139. package/dist/db/registry/subject.d.ts.map +0 -1
  140. package/dist/db/registry/types.d.ts.map +0 -1
  141. package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
  142. package/dist/db/registry/utils.d.ts.map +0 -1
  143. package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
  144. package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
  145. package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
  146. package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
  147. package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
  148. package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
  149. package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
  150. package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
  151. package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
  152. package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
  153. package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
  154. package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
  155. package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
  156. package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
  157. package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
  158. package/dist/db/schema/index.d.ts.map +0 -1
  159. package/dist/db/tenant-scope.d.ts.map +0 -1
  160. package/dist/define-config.d.ts +0 -5
  161. package/dist/define-config.d.ts.map +0 -1
  162. package/dist/handlers/consent/check.handler.d.ts.map +0 -1
  163. package/dist/handlers/consent/index.d.ts +0 -12
  164. package/dist/handlers/consent/index.d.ts.map +0 -1
  165. package/dist/handlers/init/geo.d.ts.map +0 -1
  166. package/dist/handlers/init/index.d.ts.map +0 -1
  167. package/dist/handlers/init/translations.d.ts +0 -28
  168. package/dist/handlers/init/translations.d.ts.map +0 -1
  169. package/dist/handlers/status/index.d.ts +0 -7
  170. package/dist/handlers/status/index.d.ts.map +0 -1
  171. package/dist/handlers/status/status.handler.d.ts.map +0 -1
  172. package/dist/handlers/subject/get.handler.d.ts.map +0 -1
  173. package/dist/handlers/subject/index.d.ts +0 -10
  174. package/dist/handlers/subject/index.d.ts.map +0 -1
  175. package/dist/handlers/subject/list.handler.d.ts.map +0 -1
  176. package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
  177. package/dist/handlers/subject/post.handler.d.ts.map +0 -1
  178. package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
  179. package/dist/init.d.ts.map +0 -1
  180. package/dist/middleware/auth/index.d.ts.map +0 -1
  181. package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
  182. package/dist/middleware/cors/cors.d.ts.map +0 -1
  183. package/dist/middleware/cors/index.d.ts +0 -30
  184. package/dist/middleware/cors/index.d.ts.map +0 -1
  185. package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
  186. package/dist/middleware/cors/process-cors.d.ts.map +0 -1
  187. package/dist/middleware/openapi/config.d.ts.map +0 -1
  188. package/dist/middleware/openapi/handlers.d.ts.map +0 -1
  189. package/dist/middleware/openapi/index.d.ts +0 -12
  190. package/dist/middleware/openapi/index.d.ts.map +0 -1
  191. package/dist/middleware/process-ip/index.d.ts.map +0 -1
  192. package/dist/router.d.ts.map +0 -1
  193. package/dist/routes/consent.d.ts.map +0 -1
  194. package/dist/routes/index.d.ts +0 -10
  195. package/dist/routes/index.d.ts.map +0 -1
  196. package/dist/routes/init.d.ts.map +0 -1
  197. package/dist/routes/status.d.ts.map +0 -1
  198. package/dist/routes/subject.d.ts.map +0 -1
  199. package/dist/types/api.d.ts.map +0 -1
  200. package/dist/types/index.d.ts +0 -263
  201. package/dist/types/index.d.ts.map +0 -1
  202. package/dist/utils/create-telemetry-options.d.ts.map +0 -1
  203. package/dist/utils/env.d.ts.map +0 -1
  204. package/dist/utils/extract-error-message.d.ts.map +0 -1
  205. package/dist/utils/index.d.ts +0 -4
  206. package/dist/utils/index.d.ts.map +0 -1
  207. package/dist/utils/instrumentation.d.ts.map +0 -1
  208. package/dist/utils/logger.d.ts.map +0 -1
  209. package/dist/utils/metrics.d.ts.map +0 -1
  210. package/dist/version.d.ts +0 -2
  211. package/dist/version.d.ts.map +0 -1
  212. package/knip.json +0 -31
  213. package/rslib.config.ts +0 -93
  214. package/src/cache/adapters/cloudflare-kv.ts +0 -71
  215. package/src/cache/adapters/index.ts +0 -22
  216. package/src/cache/adapters/memory.ts +0 -111
  217. package/src/cache/adapters/upstash-redis.ts +0 -113
  218. package/src/cache/gvl-resolver.ts +0 -289
  219. package/src/cache/index.ts +0 -34
  220. package/src/cache/keys.ts +0 -68
  221. package/src/cache/types.ts +0 -66
  222. package/src/core.ts +0 -369
  223. package/src/db/migrator/index.ts +0 -80
  224. package/src/db/registry/consent-policy.test.ts +0 -451
  225. package/src/db/registry/consent-policy.ts +0 -82
  226. package/src/db/registry/consent-purpose.test.ts +0 -428
  227. package/src/db/registry/consent-purpose.ts +0 -61
  228. package/src/db/registry/domain.test.ts +0 -445
  229. package/src/db/registry/domain.ts +0 -91
  230. package/src/db/registry/index.ts +0 -14
  231. package/src/db/registry/subject.test.ts +0 -371
  232. package/src/db/registry/subject.ts +0 -126
  233. package/src/db/registry/types.ts +0 -10
  234. package/src/db/registry/utils/generate-id.test.ts +0 -216
  235. package/src/db/registry/utils/generate-id.ts +0 -133
  236. package/src/db/registry/utils.ts +0 -133
  237. package/src/db/schema/1.0.0/audit-log.ts +0 -15
  238. package/src/db/schema/1.0.0/consent-policy.ts +0 -14
  239. package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
  240. package/src/db/schema/1.0.0/consent-record.ts +0 -10
  241. package/src/db/schema/1.0.0/consent.ts +0 -20
  242. package/src/db/schema/1.0.0/domain.ts +0 -12
  243. package/src/db/schema/1.0.0/index.ts +0 -48
  244. package/src/db/schema/1.0.0/subject.ts +0 -11
  245. package/src/db/schema/2.0.0/audit-log.ts +0 -18
  246. package/src/db/schema/2.0.0/consent-policy.ts +0 -28
  247. package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
  248. package/src/db/schema/2.0.0/consent.ts +0 -28
  249. package/src/db/schema/2.0.0/domain.ts +0 -12
  250. package/src/db/schema/2.0.0/index.ts +0 -47
  251. package/src/db/schema/2.0.0/subject.ts +0 -13
  252. package/src/db/schema/index.ts +0 -15
  253. package/src/db/tenant-scope.test.ts +0 -747
  254. package/src/db/tenant-scope.ts +0 -103
  255. package/src/define-config.ts +0 -5
  256. package/src/handlers/consent/check.handler.ts +0 -126
  257. package/src/handlers/init/geo.test.ts +0 -317
  258. package/src/handlers/init/geo.ts +0 -195
  259. package/src/handlers/init/index.test.ts +0 -205
  260. package/src/handlers/init/index.ts +0 -114
  261. package/src/handlers/init/translations.test.ts +0 -121
  262. package/src/handlers/init/translations.ts +0 -72
  263. package/src/handlers/status/status.handler.test.ts +0 -155
  264. package/src/handlers/status/status.handler.ts +0 -51
  265. package/src/handlers/subject/get.handler.ts +0 -92
  266. package/src/handlers/subject/list.handler.ts +0 -92
  267. package/src/handlers/subject/patch.handler.ts +0 -119
  268. package/src/handlers/subject/post.handler.test.ts +0 -294
  269. package/src/handlers/subject/post.handler.ts +0 -268
  270. package/src/handlers/utils/consent-enrichment.test.ts +0 -380
  271. package/src/handlers/utils/consent-enrichment.ts +0 -218
  272. package/src/init.test.ts +0 -126
  273. package/src/init.ts +0 -87
  274. package/src/middleware/auth/index.ts +0 -11
  275. package/src/middleware/auth/validate-api-key.test.ts +0 -86
  276. package/src/middleware/auth/validate-api-key.ts +0 -107
  277. package/src/middleware/cors/cors.test.ts +0 -135
  278. package/src/middleware/cors/cors.ts +0 -186
  279. package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
  280. package/src/middleware/cors/is-origin-trusted.ts +0 -130
  281. package/src/middleware/cors/process-cors.ts +0 -91
  282. package/src/middleware/openapi/config.ts +0 -29
  283. package/src/middleware/openapi/handlers.ts +0 -34
  284. package/src/middleware/process-ip/index.test.ts +0 -195
  285. package/src/middleware/process-ip/index.ts +0 -199
  286. package/src/router.ts +0 -15
  287. package/src/routes/consent.ts +0 -52
  288. package/src/routes/init.ts +0 -105
  289. package/src/routes/status.ts +0 -46
  290. package/src/routes/subject.ts +0 -152
  291. package/src/types/api.ts +0 -48
  292. package/src/types/index.ts +0 -297
  293. package/src/utils/create-telemetry-options.test.ts +0 -302
  294. package/src/utils/create-telemetry-options.ts +0 -229
  295. package/src/utils/env.ts +0 -84
  296. package/src/utils/extract-error-message.ts +0 -21
  297. package/src/utils/instrumentation.test.ts +0 -185
  298. package/src/utils/instrumentation.ts +0 -196
  299. package/src/utils/logger.ts +0 -41
  300. package/src/utils/metrics.test.ts +0 -323
  301. package/src/utils/metrics.ts +0 -402
  302. package/src/utils/telemetry-pii.test.ts +0 -325
  303. package/src/version.ts +0 -2
  304. package/tsconfig.json +0 -11
  305. package/vitest.config.ts +0 -28
  306. /package/dist/{types.cjs → types/index.cjs} +0 -0
  307. /package/dist/{types.js → types/index.js} +0 -0
  308. /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
  309. /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
  310. /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
  311. /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
  312. /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
  313. /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
  314. /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
- }