@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
@@ -1,229 +0,0 @@
1
- import {
2
- context,
3
- type Meter,
4
- metrics,
5
- type Span,
6
- SpanStatusCode,
7
- trace,
8
- } from '@opentelemetry/api';
9
- import type { C15TOptions } from '../types';
10
- import { version } from '../version';
11
- import { extractErrorMessage } from './extract-error-message';
12
-
13
- type TelemetryConfig = NonNullable<C15TOptions['advanced']>['telemetry'];
14
-
15
- // ── Cached config (set once during init) ──────────────────────────────
16
- let cachedConfig: TelemetryConfig | null = null;
17
- let cachedDefaultAttributes: Record<string, string | number | boolean> = {};
18
-
19
- /**
20
- * Creates telemetry configuration from provided options
21
- *
22
- * This function merges user-provided telemetry options with sensible defaults,
23
- * ensuring that service name and version are always properly set.
24
- *
25
- * Telemetry is opt-in by default - users must explicitly set enabled: true.
26
- *
27
- * @param appName - The application name to use for service.name attribute
28
- * @param telemetryConfig - Optional user-provided telemetry configuration
29
- * @param tenantId - Optional tenant ID for multi-tenant deployments
30
- * @returns Properly structured telemetry options for the OpenTelemetry SDK
31
- */
32
- export function createTelemetryOptions(
33
- appName = 'c15t',
34
- telemetryConfig?: TelemetryConfig,
35
- tenantId?: string
36
- ): TelemetryConfig {
37
- const defaultAttributes: Record<string, string | number | boolean> = {
38
- ...(telemetryConfig?.defaultAttributes || {}),
39
-
40
- // Always ensure these core attributes are set
41
- 'service.name': String(appName),
42
- 'service.version': version,
43
- };
44
-
45
- if (tenantId) {
46
- defaultAttributes['tenant.id'] = tenantId;
47
- }
48
-
49
- const config: TelemetryConfig = {
50
- // Opt-in: disabled by default, must be explicitly enabled
51
- enabled: telemetryConfig?.enabled ?? false,
52
- tracer: telemetryConfig?.tracer,
53
- meter: telemetryConfig?.meter,
54
- defaultAttributes,
55
- };
56
-
57
- // Cache for use without explicit options
58
- cachedConfig = config;
59
- cachedDefaultAttributes = defaultAttributes;
60
-
61
- return config;
62
- }
63
-
64
- /**
65
- * Checks if telemetry is enabled.
66
- * When called without options, uses the cached config from init.
67
- */
68
- export function isTelemetryEnabled(options?: C15TOptions): boolean {
69
- if (options) {
70
- return options.advanced?.telemetry?.enabled === true;
71
- }
72
- return cachedConfig?.enabled === true;
73
- }
74
-
75
- /**
76
- * Gets the tracer for the c15t backend.
77
- * When called without options, uses the cached config from init.
78
- */
79
- export const getTracer = (options?: C15TOptions) => {
80
- if (!isTelemetryEnabled(options)) {
81
- // Return a no-op tracer when telemetry is disabled
82
- return trace.getTracer('c15t-noop');
83
- }
84
- const tracer = options?.advanced?.telemetry?.tracer ?? cachedConfig?.tracer;
85
- if (tracer) {
86
- return tracer;
87
- }
88
- return trace.getTracer(options?.appName ?? 'c15t');
89
- };
90
-
91
- /**
92
- * Gets the meter for the c15t backend.
93
- * When called without options, uses the cached config from init.
94
- */
95
- export const getMeter = (options?: C15TOptions): Meter => {
96
- if (!isTelemetryEnabled(options)) {
97
- // Return a no-op meter when telemetry is disabled
98
- return metrics.getMeter('c15t-noop');
99
- }
100
- const meter = options?.advanced?.telemetry?.meter ?? cachedConfig?.meter;
101
- if (meter) {
102
- return meter;
103
- }
104
- return metrics.getMeter(options?.appName ?? 'c15t');
105
- };
106
-
107
- /**
108
- * Gets the cached default attributes.
109
- * Used by span wrappers when no explicit options are provided.
110
- */
111
- export function getDefaultAttributes(): Record<
112
- string,
113
- string | number | boolean
114
- > {
115
- return cachedDefaultAttributes;
116
- }
117
-
118
- /**
119
- * Resets the cached telemetry config (for testing).
120
- */
121
- export function resetTelemetryConfig(): void {
122
- cachedConfig = null;
123
- cachedDefaultAttributes = {};
124
- }
125
-
126
- /**
127
- * Creates a span for an API request
128
- */
129
- export const createRequestSpan = (
130
- method: string,
131
- path: string,
132
- options?: C15TOptions
133
- ) => {
134
- if (!isTelemetryEnabled(options)) {
135
- return null;
136
- }
137
-
138
- const tracer = getTracer(options);
139
- const defaultAttrs =
140
- options?.advanced?.telemetry?.defaultAttributes || getDefaultAttributes();
141
-
142
- const span = tracer.startSpan(`${method} ${path}`, {
143
- attributes: {
144
- 'http.method': method,
145
- ...defaultAttrs,
146
- },
147
- });
148
-
149
- return span;
150
- };
151
-
152
- /**
153
- * Wraps an API request handler in a span.
154
- * The span is set as active context so child spans nest correctly.
155
- */
156
- export const withRequestSpan = async <T>(
157
- method: string,
158
- path: string,
159
- operation: () => Promise<T>,
160
- options?: C15TOptions
161
- ): Promise<T> => {
162
- const span = createRequestSpan(method, path, options);
163
-
164
- if (!span) {
165
- return operation();
166
- }
167
-
168
- try {
169
- const result = await withSpanContext(span, operation);
170
- span.setStatus({ code: SpanStatusCode.OK });
171
- return result;
172
- } catch (error) {
173
- handleSpanError(span, error);
174
- throw error;
175
- } finally {
176
- span.end();
177
- }
178
- };
179
-
180
- /**
181
- * Handles errors in spans
182
- */
183
- export const handleSpanError = (span: Span, error: unknown) => {
184
- span.setStatus({
185
- code: SpanStatusCode.ERROR,
186
- message: extractErrorMessage(error),
187
- });
188
-
189
- if (error instanceof Error) {
190
- span.setAttribute('error.type', error.name);
191
- }
192
- };
193
-
194
- /**
195
- * Gets the current trace context for log correlation.
196
- * Returns trace and span IDs from the active span.
197
- *
198
- * @returns Object with traceId and spanId, or null if no active span
199
- */
200
- export function getTraceContext(): {
201
- traceId: string;
202
- spanId: string;
203
- } | null {
204
- const activeSpan = trace.getActiveSpan();
205
- if (!activeSpan) {
206
- return null;
207
- }
208
-
209
- const spanContext = activeSpan.spanContext();
210
- if (!spanContext) {
211
- return null;
212
- }
213
-
214
- return {
215
- traceId: spanContext.traceId,
216
- spanId: spanContext.spanId,
217
- };
218
- }
219
-
220
- /**
221
- * Runs a function within a span context, making the span active.
222
- * This allows nested operations to access the parent span via trace.getActiveSpan().
223
- */
224
- export const withSpanContext = async <T>(
225
- span: Span,
226
- operation: () => Promise<T>
227
- ): Promise<T> => {
228
- return context.with(trace.setSpan(context.active(), span), operation);
229
- };
package/src/utils/env.ts DELETED
@@ -1,84 +0,0 @@
1
- /**
2
- * Environment variables object
3
- *
4
- * Provides access to environment variables in a way that works in both
5
- * browser and Node.js environments. In Node.js, this will be process.env,
6
- * and in browsers, it will be an empty object.
7
- *
8
- * @returns An object containing environment variables accessible in the current runtime
9
- *
10
- * @example
11
- * ```ts
12
- * // Access an environment variable
13
- * const apiKey = env.API_KEY;
14
- * ```
15
- */
16
- export const env = typeof process !== 'undefined' ? process.env : {};
17
-
18
- /**
19
- * Determines if the application is running in production mode
20
- *
21
- * Checks if NODE_ENV is set to 'production'. This is useful for
22
- * conditionally enabling or disabling features based on the environment.
23
- *
24
- * @returns Boolean indicating whether the application is running in production mode
25
- *
26
- * @example
27
- * ```ts
28
- * // Conditionally execute code based on environment
29
- * if (isProduction) {
30
- * // Production-only code
31
- * }
32
- * ```
33
- */
34
- export const isProduction =
35
- typeof process !== 'undefined' && process.env.NODE_ENV === 'production';
36
-
37
- /**
38
- * Converts a string or boolean value to a boolean
39
- *
40
- * @param val - The value to convert to boolean
41
- * @returns `false` if the value is falsy or the string 'false', otherwise `true`
42
- *
43
- * @example
44
- * ```ts
45
- * toBoolean('true'); // true
46
- * toBoolean('false'); // false
47
- * toBoolean(undefined); // false
48
- * toBoolean(true); // true
49
- * ```
50
- *
51
- * @internal Used for environment variable parsing
52
- */
53
- function toBoolean(val: boolean | string | undefined) {
54
- return val ? val !== 'false' : false;
55
- }
56
-
57
- /**
58
- * The current Node.js environment value
59
- *
60
- * Retrieves the NODE_ENV environment variable value if available,
61
- * otherwise returns an empty string.
62
- *
63
- * @returns The current NODE_ENV value or empty string if not set
64
- */
65
- export const nodeENV =
66
- (typeof process !== 'undefined' && process.env && process.env.NODE_ENV) || '';
67
-
68
- /**
69
- * Determines if the application is running in test mode
70
- *
71
- * Checks if NODE_ENV is set to 'test' or if the TEST environment
72
- * variable is truthy and not 'false'.
73
- *
74
- * @returns Boolean indicating whether the application is running in test mode
75
- *
76
- * @example
77
- * ```ts
78
- * // Skip expensive operations in tests
79
- * if (!isTest) {
80
- * runExpensiveOperation();
81
- * }
82
- * ```
83
- */
84
- export const isTest = nodeENV === 'test' || toBoolean(env.TEST);
@@ -1,21 +0,0 @@
1
- /**
2
- * Extracts a useful error message from any error type.
3
- *
4
- * Handles `AggregateError` (e.g. from Node.js `net.connect` failing on both
5
- * IPv4/IPv6) where `error.message` is empty but `error.errors[]` contains the
6
- * real messages.
7
- */
8
- export function extractErrorMessage(error: unknown): string {
9
- if (error instanceof AggregateError && error.errors?.length > 0) {
10
- const inner = error.errors
11
- .map((e: unknown) => (e instanceof Error ? e.message : String(e)))
12
- .join('; ');
13
- return `AggregateError: ${inner}`;
14
- }
15
-
16
- if (error instanceof Error) {
17
- return error.message || error.name;
18
- }
19
-
20
- return String(error);
21
- }
@@ -1,185 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
- import type { C15TOptions } from '../types';
3
- import {
4
- withCacheSpan,
5
- withDatabaseSpan,
6
- withExternalSpan,
7
- } from './instrumentation';
8
-
9
- // Mock create-telemetry-options
10
- vi.mock('./create-telemetry-options', () => {
11
- const { SpanStatusCode } = require('@opentelemetry/api');
12
-
13
- const mockSpan = () => ({
14
- setStatus: vi.fn(),
15
- setAttribute: vi.fn(),
16
- updateName: vi.fn(),
17
- end: vi.fn(),
18
- });
19
-
20
- return {
21
- isTelemetryEnabled: vi.fn(
22
- (options) => options?.advanced?.telemetry?.enabled === true
23
- ),
24
- getTracer: vi.fn(() => ({
25
- startSpan: vi.fn(() => mockSpan()),
26
- })),
27
- getDefaultAttributes: vi.fn(() => ({
28
- 'service.name': 'test',
29
- 'service.version': '1.0.0',
30
- })),
31
- withSpanContext: vi.fn((_span, operation) => operation()),
32
- handleSpanError: vi.fn((span, error) => {
33
- span.setStatus({
34
- code: SpanStatusCode.ERROR,
35
- message: error instanceof Error ? error.message : String(error),
36
- });
37
- if (error instanceof Error) {
38
- span.setAttribute('error.type', error.name);
39
- }
40
- }),
41
- };
42
- });
43
-
44
- afterEach(() => {
45
- vi.clearAllMocks();
46
- });
47
-
48
- const enabledOptions: C15TOptions = {
49
- trustedOrigins: [],
50
- adapter: {} as C15TOptions['adapter'],
51
- advanced: {
52
- telemetry: {
53
- enabled: true,
54
- },
55
- },
56
- };
57
-
58
- describe('withDatabaseSpan', () => {
59
- it('returns operation result when telemetry is disabled', async () => {
60
- const result = await withDatabaseSpan(
61
- { operation: 'find', entity: 'subject' },
62
- async () => ({ id: '123', name: 'test' })
63
- );
64
-
65
- expect(result).toEqual({ id: '123', name: 'test' });
66
- });
67
-
68
- it('returns operation result when telemetry is enabled', async () => {
69
- const result = await withDatabaseSpan(
70
- { operation: 'find', entity: 'subject' },
71
- async () => ({ id: '123', name: 'test' }),
72
- enabledOptions
73
- );
74
-
75
- expect(result).toEqual({ id: '123', name: 'test' });
76
- });
77
-
78
- it('propagates errors from operation', async () => {
79
- const error = new Error('DB connection failed');
80
-
81
- await expect(
82
- withDatabaseSpan(
83
- { operation: 'find', entity: 'subject' },
84
- async () => {
85
- throw error;
86
- },
87
- enabledOptions
88
- )
89
- ).rejects.toThrow('DB connection failed');
90
- });
91
-
92
- it('executes operation without span when telemetry is disabled', async () => {
93
- const operation = vi.fn().mockResolvedValue('result');
94
-
95
- const result = await withDatabaseSpan(
96
- { operation: 'create', entity: 'consent' },
97
- operation
98
- );
99
-
100
- expect(result).toBe('result');
101
- expect(operation).toHaveBeenCalledTimes(1);
102
- });
103
- });
104
-
105
- describe('withExternalSpan', () => {
106
- it('returns operation result when telemetry is disabled', async () => {
107
- const result = await withExternalSpan(
108
- { url: 'https://example.com/api', method: 'GET' },
109
- async () => ({ status: 200 })
110
- );
111
-
112
- expect(result).toEqual({ status: 200 });
113
- });
114
-
115
- it('returns operation result when telemetry is enabled', async () => {
116
- const result = await withExternalSpan(
117
- { url: 'https://example.com/api', method: 'GET' },
118
- async () => ({ status: 200 }),
119
- enabledOptions
120
- );
121
-
122
- expect(result).toEqual({ status: 200 });
123
- });
124
-
125
- it('propagates errors from operation', async () => {
126
- const error = new Error('Network error');
127
-
128
- await expect(
129
- withExternalSpan(
130
- { url: 'https://example.com/api', method: 'POST' },
131
- async () => {
132
- throw error;
133
- },
134
- enabledOptions
135
- )
136
- ).rejects.toThrow('Network error');
137
- });
138
- });
139
-
140
- describe('withCacheSpan', () => {
141
- it('returns operation result when telemetry is disabled', async () => {
142
- const result = await withCacheSpan('get', 'memory', async () => ({
143
- data: 'cached',
144
- }));
145
-
146
- expect(result).toEqual({ data: 'cached' });
147
- });
148
-
149
- it('returns operation result when telemetry is enabled', async () => {
150
- const result = await withCacheSpan(
151
- 'get',
152
- 'external',
153
- async () => ({ data: 'cached' }),
154
- enabledOptions
155
- );
156
-
157
- expect(result).toEqual({ data: 'cached' });
158
- });
159
-
160
- it('returns null for cache miss', async () => {
161
- const result = await withCacheSpan(
162
- 'get',
163
- 'memory',
164
- async () => null,
165
- enabledOptions
166
- );
167
-
168
- expect(result).toBeNull();
169
- });
170
-
171
- it('propagates errors from operation', async () => {
172
- const error = new Error('Cache connection failed');
173
-
174
- await expect(
175
- withCacheSpan(
176
- 'get',
177
- 'external',
178
- async () => {
179
- throw error;
180
- },
181
- enabledOptions
182
- )
183
- ).rejects.toThrow('Cache connection failed');
184
- });
185
- });
@@ -1,196 +0,0 @@
1
- import type { Span } from '@opentelemetry/api';
2
- import { SpanKind, SpanStatusCode } from '@opentelemetry/api';
3
- import type { C15TOptions } from '../types';
4
- import {
5
- getDefaultAttributes,
6
- getTracer,
7
- handleSpanError,
8
- isTelemetryEnabled,
9
- withSpanContext,
10
- } from './create-telemetry-options';
11
-
12
- /**
13
- * Span attributes for database operations
14
- */
15
- export interface DatabaseSpanAttributes {
16
- /** The database operation type (find, create, update, delete) */
17
- operation: 'find' | 'create' | 'update' | 'delete' | 'findOrCreate';
18
- /** The entity type being operated on */
19
- entity: string;
20
- /** Optional additional attributes */
21
- [key: string]: string | number | boolean | undefined;
22
- }
23
-
24
- /**
25
- * Span attributes for external API calls
26
- */
27
- export interface ExternalSpanAttributes {
28
- /** The URL being called */
29
- url: string;
30
- /** The HTTP method */
31
- method: string;
32
- /** Optional additional attributes */
33
- [key: string]: string | number | boolean | undefined;
34
- }
35
-
36
- /**
37
- * Execute an async operation within a span, handling status and error recording.
38
- *
39
- * Sets SpanStatusCode.OK on success, records error attributes and sets
40
- * SpanStatusCode.ERROR on failure, and always ends the span.
41
- */
42
- async function executeWithSpan<T>(
43
- span: Span,
44
- operation: () => Promise<T>
45
- ): Promise<T> {
46
- try {
47
- const result = await withSpanContext(span, operation);
48
- span.setStatus({ code: SpanStatusCode.OK });
49
- return result;
50
- } catch (error) {
51
- handleSpanError(span, error);
52
- throw error;
53
- } finally {
54
- span.end();
55
- }
56
- }
57
-
58
- /**
59
- * Resolves default attributes from explicit options or the cached config.
60
- */
61
- function resolveDefaultAttributes(
62
- options?: C15TOptions
63
- ): Record<string, string | number | boolean> {
64
- return (
65
- options?.advanced?.telemetry?.defaultAttributes || getDefaultAttributes()
66
- );
67
- }
68
-
69
- /**
70
- * Wraps a database operation in a span for tracing.
71
- *
72
- * @param attributes - Span attributes describing the operation
73
- * @param operation - The async operation to wrap
74
- * @param options - C15T options for telemetry configuration
75
- * @returns The result of the operation
76
- *
77
- * @example
78
- * ```typescript
79
- * const subject = await withDatabaseSpan(
80
- * { operation: 'find', entity: 'subject' },
81
- * async () => db.subject.findUnique({ where: { id } }),
82
- * options
83
- * );
84
- * ```
85
- */
86
- export async function withDatabaseSpan<T>(
87
- attributes: DatabaseSpanAttributes,
88
- operation: () => Promise<T>,
89
- options?: C15TOptions
90
- ): Promise<T> {
91
- if (!isTelemetryEnabled(options)) {
92
- return operation();
93
- }
94
-
95
- const tracer = getTracer(options);
96
- const spanName = `db.${attributes.entity}.${attributes.operation}`;
97
-
98
- const span = tracer.startSpan(spanName, {
99
- kind: SpanKind.CLIENT,
100
- attributes: {
101
- 'db.system': 'c15t',
102
- 'db.operation': attributes.operation,
103
- 'db.entity': attributes.entity,
104
- ...resolveDefaultAttributes(options),
105
- ...Object.fromEntries(
106
- Object.entries(attributes).filter(
107
- ([key]) => !['operation', 'entity'].includes(key)
108
- )
109
- ),
110
- },
111
- });
112
-
113
- return executeWithSpan(span, operation);
114
- }
115
-
116
- /**
117
- * Wraps an external API call in a span for tracing.
118
- *
119
- * @param attributes - Span attributes describing the external call
120
- * @param operation - The async operation to wrap
121
- * @param options - C15T options for telemetry configuration
122
- * @returns The result of the operation
123
- *
124
- * @example
125
- * ```typescript
126
- * const response = await withExternalSpan(
127
- * { url: 'https://api.example.com/data', method: 'GET' },
128
- * async () => fetch('https://api.example.com/data'),
129
- * options
130
- * );
131
- * ```
132
- */
133
- export async function withExternalSpan<T>(
134
- attributes: ExternalSpanAttributes,
135
- operation: () => Promise<T>,
136
- options?: C15TOptions
137
- ): Promise<T> {
138
- if (!isTelemetryEnabled(options)) {
139
- return operation();
140
- }
141
-
142
- const tracer = getTracer(options);
143
- const url = new URL(attributes.url);
144
- const spanName = `HTTP ${attributes.method} ${url.hostname}`;
145
-
146
- const span = tracer.startSpan(spanName, {
147
- kind: SpanKind.CLIENT,
148
- attributes: {
149
- 'http.method': attributes.method,
150
- 'http.url': `${url.origin}${url.pathname}`,
151
- 'http.host': url.hostname,
152
- ...resolveDefaultAttributes(options),
153
- ...Object.fromEntries(
154
- Object.entries(attributes).filter(
155
- ([key]) => !['url', 'method'].includes(key)
156
- )
157
- ),
158
- },
159
- });
160
-
161
- return executeWithSpan(span, operation);
162
- }
163
-
164
- /**
165
- * Wraps a cache operation in a span for tracing.
166
- *
167
- * @param operation - The cache operation type
168
- * @param layer - The cache layer (bundled, memory, external)
169
- * @param fn - The async operation to wrap
170
- * @param options - C15T options for telemetry configuration
171
- * @returns The result of the operation
172
- */
173
- export async function withCacheSpan<T>(
174
- operation: 'get' | 'set' | 'delete',
175
- layer: 'bundled' | 'memory' | 'external',
176
- fn: () => Promise<T>,
177
- options?: C15TOptions
178
- ): Promise<T> {
179
- if (!isTelemetryEnabled(options)) {
180
- return fn();
181
- }
182
-
183
- const tracer = getTracer(options);
184
- const spanName = `cache.${layer}.${operation}`;
185
-
186
- const span = tracer.startSpan(spanName, {
187
- kind: SpanKind.CLIENT,
188
- attributes: {
189
- 'cache.operation': operation,
190
- 'cache.layer': layer,
191
- ...resolveDefaultAttributes(options),
192
- },
193
- });
194
-
195
- return executeWithSpan(span, fn);
196
- }