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