@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,252 @@
|
|
|
1
|
+
import { baseTranslations } from '@c15t/translations';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { showConsentBannerContract } from './show-banner.contract';
|
|
5
|
+
|
|
6
|
+
// Add custom tests specific to the show-banner contract
|
|
7
|
+
describe('Show Consent Banner Contract Custom Tests', () => {
|
|
8
|
+
// Helper to access schemas consistently throughout tests
|
|
9
|
+
const schemas = {
|
|
10
|
+
input: showConsentBannerContract['~orpc'].inputSchema,
|
|
11
|
+
output: showConsentBannerContract['~orpc'].outputSchema,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const validateOutput = (output: unknown) => {
|
|
15
|
+
return schemas.output?.safeParse(output);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('Output Validation', () => {
|
|
19
|
+
describe('Required fields', () => {
|
|
20
|
+
it('validates complete output object', () => {
|
|
21
|
+
const validOutput = {
|
|
22
|
+
showConsentBanner: true,
|
|
23
|
+
jurisdiction: {
|
|
24
|
+
code: 'GDPR',
|
|
25
|
+
message: 'GDPR or equivalent regulations require a cookie banner.',
|
|
26
|
+
},
|
|
27
|
+
location: {
|
|
28
|
+
countryCode: 'DE',
|
|
29
|
+
regionCode: null,
|
|
30
|
+
},
|
|
31
|
+
translations: {
|
|
32
|
+
translations: baseTranslations.en,
|
|
33
|
+
language: 'en',
|
|
34
|
+
},
|
|
35
|
+
branding: 'c15t',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const result = validateOutput(validOutput);
|
|
39
|
+
expect(result?.success).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('rejects output without required fields', () => {
|
|
43
|
+
const invalidOutput = {
|
|
44
|
+
showConsentBanner: true,
|
|
45
|
+
// Missing jurisdiction and location
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const result = validateOutput(invalidOutput);
|
|
49
|
+
expect(result?.success).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('Jurisdiction validation', () => {
|
|
54
|
+
it('validates all supported jurisdiction codes', () => {
|
|
55
|
+
const jurisdictionCodes = [
|
|
56
|
+
'GDPR',
|
|
57
|
+
'CH',
|
|
58
|
+
'BR',
|
|
59
|
+
'PIPEDA',
|
|
60
|
+
'AU',
|
|
61
|
+
'APPI',
|
|
62
|
+
'PIPA',
|
|
63
|
+
'NONE',
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
for (const code of jurisdictionCodes) {
|
|
67
|
+
const output = {
|
|
68
|
+
showConsentBanner: true,
|
|
69
|
+
jurisdiction: {
|
|
70
|
+
code,
|
|
71
|
+
message: 'Test message',
|
|
72
|
+
},
|
|
73
|
+
location: {
|
|
74
|
+
countryCode: 'US',
|
|
75
|
+
regionCode: null,
|
|
76
|
+
},
|
|
77
|
+
translations: {
|
|
78
|
+
translations: baseTranslations.en,
|
|
79
|
+
language: 'en',
|
|
80
|
+
},
|
|
81
|
+
branding: 'c15t',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const result = validateOutput(output);
|
|
85
|
+
expect(result?.success).toBe(true);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('rejects invalid jurisdiction codes', () => {
|
|
90
|
+
const output = {
|
|
91
|
+
showConsentBanner: true,
|
|
92
|
+
jurisdiction: {
|
|
93
|
+
code: 'INVALID_CODE', // Invalid code
|
|
94
|
+
message: 'Test message',
|
|
95
|
+
},
|
|
96
|
+
location: {
|
|
97
|
+
countryCode: 'US',
|
|
98
|
+
regionCode: null,
|
|
99
|
+
},
|
|
100
|
+
translations: {
|
|
101
|
+
translations: baseTranslations.en,
|
|
102
|
+
language: 'en',
|
|
103
|
+
},
|
|
104
|
+
branding: 'c15t',
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const result = validateOutput(output);
|
|
108
|
+
expect(result?.success).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('Location validation', () => {
|
|
113
|
+
it('accepts null country and region codes', () => {
|
|
114
|
+
const output = {
|
|
115
|
+
showConsentBanner: false,
|
|
116
|
+
jurisdiction: {
|
|
117
|
+
code: 'NONE',
|
|
118
|
+
message: 'No specific requirements',
|
|
119
|
+
},
|
|
120
|
+
location: {
|
|
121
|
+
countryCode: null,
|
|
122
|
+
regionCode: null,
|
|
123
|
+
},
|
|
124
|
+
translations: {
|
|
125
|
+
translations: baseTranslations.en,
|
|
126
|
+
language: 'en',
|
|
127
|
+
},
|
|
128
|
+
branding: 'c15t',
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const result = validateOutput(output);
|
|
132
|
+
expect(result?.success).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('accepts valid country and region codes', () => {
|
|
136
|
+
const output = {
|
|
137
|
+
showConsentBanner: true,
|
|
138
|
+
jurisdiction: {
|
|
139
|
+
code: 'GDPR',
|
|
140
|
+
message: 'GDPR applies',
|
|
141
|
+
},
|
|
142
|
+
location: {
|
|
143
|
+
countryCode: 'DE',
|
|
144
|
+
regionCode: 'BY',
|
|
145
|
+
},
|
|
146
|
+
translations: {
|
|
147
|
+
translations: baseTranslations.en,
|
|
148
|
+
language: 'en',
|
|
149
|
+
},
|
|
150
|
+
branding: 'c15t',
|
|
151
|
+
};
|
|
152
|
+
const result = validateOutput(output);
|
|
153
|
+
expect(result?.success).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('rejects non-string non-null country codes', () => {
|
|
157
|
+
const output = {
|
|
158
|
+
showConsentBanner: true,
|
|
159
|
+
jurisdiction: {
|
|
160
|
+
code: 'GDPR',
|
|
161
|
+
message: 'GDPR applies',
|
|
162
|
+
},
|
|
163
|
+
location: {
|
|
164
|
+
countryCode: 123, // Invalid type
|
|
165
|
+
regionCode: null,
|
|
166
|
+
},
|
|
167
|
+
translations: {
|
|
168
|
+
translations: baseTranslations.en,
|
|
169
|
+
language: 'en',
|
|
170
|
+
},
|
|
171
|
+
branding: 'c15t',
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Need to use type assertion to bypass TypeScript
|
|
175
|
+
const result = validateOutput(output);
|
|
176
|
+
expect(result?.success).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('ShowConsentBanner flag', () => {
|
|
181
|
+
it('validates boolean value', () => {
|
|
182
|
+
const trueOutput = {
|
|
183
|
+
showConsentBanner: true,
|
|
184
|
+
jurisdiction: {
|
|
185
|
+
code: 'GDPR',
|
|
186
|
+
message: 'GDPR applies',
|
|
187
|
+
},
|
|
188
|
+
location: {
|
|
189
|
+
countryCode: 'DE',
|
|
190
|
+
regionCode: null,
|
|
191
|
+
},
|
|
192
|
+
translations: {
|
|
193
|
+
translations: baseTranslations.en,
|
|
194
|
+
language: 'en',
|
|
195
|
+
},
|
|
196
|
+
branding: 'c15t',
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const falseOutput = {
|
|
200
|
+
showConsentBanner: false,
|
|
201
|
+
jurisdiction: {
|
|
202
|
+
code: 'NONE',
|
|
203
|
+
message: 'No requirements',
|
|
204
|
+
},
|
|
205
|
+
location: {
|
|
206
|
+
countryCode: 'US',
|
|
207
|
+
regionCode: null,
|
|
208
|
+
},
|
|
209
|
+
translations: {
|
|
210
|
+
translations: baseTranslations.en,
|
|
211
|
+
language: 'en',
|
|
212
|
+
},
|
|
213
|
+
branding: 'c15t',
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
expect(validateOutput(trueOutput)?.success).toBe(true);
|
|
217
|
+
expect(validateOutput(falseOutput)?.success).toBe(true);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('rejects non-boolean values', () => {
|
|
221
|
+
const invalidOutput = {
|
|
222
|
+
showConsentBanner: 'yes', // Invalid type
|
|
223
|
+
jurisdiction: {
|
|
224
|
+
code: 'GDPR',
|
|
225
|
+
message: 'GDPR applies',
|
|
226
|
+
},
|
|
227
|
+
location: {
|
|
228
|
+
countryCode: 'DE',
|
|
229
|
+
regionCode: null,
|
|
230
|
+
},
|
|
231
|
+
translations: {
|
|
232
|
+
translations: baseTranslations.en,
|
|
233
|
+
language: 'en',
|
|
234
|
+
},
|
|
235
|
+
branding: 'c15t',
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Need to use type assertion to bypass TypeScript
|
|
239
|
+
const result = validateOutput(invalidOutput);
|
|
240
|
+
expect(result?.success).toBe(false);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// // Add required fields testing using the utility
|
|
247
|
+
// // No required fields for input since it's an empty object
|
|
248
|
+
// tester.testRequiredFields('output', [
|
|
249
|
+
// 'showConsentBanner',
|
|
250
|
+
// 'jurisdiction',
|
|
251
|
+
// 'location',
|
|
252
|
+
// ]);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { branding } from '~/v2/types';
|
|
4
|
+
import { JurisdictionInfoSchema } from '../shared/jurisdiction.schema';
|
|
5
|
+
|
|
6
|
+
const TitleDescriptionSchema = z.object({
|
|
7
|
+
title: z.string(),
|
|
8
|
+
description: z.string(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const TranslationsSchema = z.object({
|
|
12
|
+
common: z.object({
|
|
13
|
+
acceptAll: z.string(),
|
|
14
|
+
rejectAll: z.string(),
|
|
15
|
+
customize: z.string(),
|
|
16
|
+
save: z.string(),
|
|
17
|
+
}),
|
|
18
|
+
cookieBanner: TitleDescriptionSchema,
|
|
19
|
+
consentManagerDialog: TitleDescriptionSchema,
|
|
20
|
+
consentTypes: z.object({
|
|
21
|
+
experience: TitleDescriptionSchema,
|
|
22
|
+
functionality: TitleDescriptionSchema,
|
|
23
|
+
marketing: TitleDescriptionSchema,
|
|
24
|
+
measurement: TitleDescriptionSchema,
|
|
25
|
+
necessary: TitleDescriptionSchema,
|
|
26
|
+
}),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const showConsentBannerContract = oc
|
|
30
|
+
.route({
|
|
31
|
+
method: 'GET',
|
|
32
|
+
path: '/show-consent-banner',
|
|
33
|
+
description: `Determines if a user should see a consent banner based on their location and applicable privacy regulations.
|
|
34
|
+
This endpoint performs the following checks:
|
|
35
|
+
|
|
36
|
+
1. Detects the user's location using various header information:
|
|
37
|
+
- Cloudflare country headers
|
|
38
|
+
- Vercel IP country headers
|
|
39
|
+
- AWS CloudFront headers
|
|
40
|
+
- Custom country code headers
|
|
41
|
+
|
|
42
|
+
2. Determines the applicable jurisdiction based on the location:
|
|
43
|
+
- GDPR (EU/EEA/UK)
|
|
44
|
+
- Swiss Data Protection Act
|
|
45
|
+
- LGPD (Brazil)
|
|
46
|
+
- PIPEDA (Canada)
|
|
47
|
+
- Australian Privacy Principles
|
|
48
|
+
- APPI (Japan)
|
|
49
|
+
- PIPA (South Korea)
|
|
50
|
+
|
|
51
|
+
3. Returns detailed information about:
|
|
52
|
+
- Whether to show the consent banner
|
|
53
|
+
- The applicable jurisdiction and its requirements
|
|
54
|
+
- The user's detected location (country and region)
|
|
55
|
+
|
|
56
|
+
Use this endpoint to implement geo-targeted consent banners and ensure compliance with regional privacy regulations.`,
|
|
57
|
+
tags: ['cookie-banner'],
|
|
58
|
+
})
|
|
59
|
+
.output(
|
|
60
|
+
z.object({
|
|
61
|
+
showConsentBanner: z.boolean(),
|
|
62
|
+
jurisdiction: JurisdictionInfoSchema,
|
|
63
|
+
location: z.object({
|
|
64
|
+
countryCode: z.string().nullable(),
|
|
65
|
+
regionCode: z.string().nullable(),
|
|
66
|
+
}),
|
|
67
|
+
translations: z.object({
|
|
68
|
+
language: z.string(),
|
|
69
|
+
translations: TranslationsSchema,
|
|
70
|
+
}),
|
|
71
|
+
branding: z.enum(branding),
|
|
72
|
+
})
|
|
73
|
+
);
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { createContractTests } from '~/v2/contracts/test.utils';
|
|
4
|
+
import { verifyConsentContract } from './verify.contract';
|
|
5
|
+
|
|
6
|
+
// Create base tests for the contract using the utility
|
|
7
|
+
const tester = createContractTests('Verify Consent', verifyConsentContract);
|
|
8
|
+
|
|
9
|
+
// Custom tests specific to verify consent
|
|
10
|
+
describe('Verify Consent Contract Custom Tests', () => {
|
|
11
|
+
// Helper to access schemas consistently throughout tests
|
|
12
|
+
const schemas = {
|
|
13
|
+
input: verifyConsentContract['~orpc'].inputSchema,
|
|
14
|
+
output: verifyConsentContract['~orpc'].outputSchema,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Helper functions for common test patterns
|
|
18
|
+
const validateInput = (input: unknown) => {
|
|
19
|
+
return schemas.input?.safeParse(input);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const validateOutput = (output: unknown) => {
|
|
23
|
+
return schemas.output?.safeParse(output);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe('Input Validation', () => {
|
|
27
|
+
it('accepts valid input with minimum required fields', () => {
|
|
28
|
+
const validInput = {
|
|
29
|
+
domain: 'example.com',
|
|
30
|
+
type: 'cookie_banner',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const result = validateInput(validInput);
|
|
34
|
+
expect(result?.success).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('accepts valid input with all fields', () => {
|
|
38
|
+
const validInput = {
|
|
39
|
+
subjectId: 'subject-123',
|
|
40
|
+
externalSubjectId: 'ext-123',
|
|
41
|
+
domain: 'example.com',
|
|
42
|
+
type: 'privacy_policy',
|
|
43
|
+
policyId: 'policy-123',
|
|
44
|
+
preferences: ['analytics', 'marketing'],
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const result = validateInput(validInput);
|
|
48
|
+
expect(result?.success).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rejects input without required domain', () => {
|
|
52
|
+
const invalidInput = {
|
|
53
|
+
type: 'cookie_banner',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const result = validateInput(invalidInput);
|
|
57
|
+
expect(result?.success).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('rejects input without required type', () => {
|
|
61
|
+
const invalidInput = {
|
|
62
|
+
domain: 'example.com',
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const result = validateInput(invalidInput);
|
|
66
|
+
expect(result?.success).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('rejects input with invalid type', () => {
|
|
70
|
+
const invalidInput = {
|
|
71
|
+
domain: 'example.com',
|
|
72
|
+
type: 'invalid_type', // Not in PolicyTypeSchema
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const result = validateInput(invalidInput);
|
|
76
|
+
expect(result?.success).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('rejects input with extra properties', () => {
|
|
80
|
+
const invalidInput = {
|
|
81
|
+
domain: 'example.com',
|
|
82
|
+
type: 'cookie_banner',
|
|
83
|
+
extraProperty: 'should not be allowed',
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const result = validateInput(invalidInput);
|
|
87
|
+
expect(result?.success).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('validates preferences as array of strings', () => {
|
|
91
|
+
const validInput = {
|
|
92
|
+
domain: 'example.com',
|
|
93
|
+
type: 'cookie_banner',
|
|
94
|
+
preferences: ['analytics', 'marketing'],
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
expect(validateInput(validInput)?.success).toBe(true);
|
|
98
|
+
|
|
99
|
+
const invalidInput = {
|
|
100
|
+
domain: 'example.com',
|
|
101
|
+
type: 'cookie_banner',
|
|
102
|
+
preferences: { analytics: true }, // Object instead of array
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
expect(validateInput(invalidInput)?.success).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Output Validation', () => {
|
|
110
|
+
it('validates successful consent verification', () => {
|
|
111
|
+
const validOutput = {
|
|
112
|
+
isValid: true,
|
|
113
|
+
consent: {
|
|
114
|
+
id: 'consent-123',
|
|
115
|
+
purposeIds: ['analytics', 'marketing'],
|
|
116
|
+
additionalProperty: 'allowed by passthrough',
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result = validateOutput(validOutput);
|
|
121
|
+
expect(result?.success).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('validates unsuccessful consent verification with reasons', () => {
|
|
125
|
+
const validOutput = {
|
|
126
|
+
isValid: false,
|
|
127
|
+
reasons: ['No consent found for the given policy'],
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const result = validateOutput(validOutput);
|
|
131
|
+
expect(result?.success).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('rejects output without required isValid field', () => {
|
|
135
|
+
const invalidOutput = {
|
|
136
|
+
reasons: ['Some reason'],
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const result = validateOutput(invalidOutput);
|
|
140
|
+
expect(result?.success).toBe(false);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('validates consent object structure', () => {
|
|
144
|
+
const invalidOutput = {
|
|
145
|
+
isValid: true,
|
|
146
|
+
consent: {
|
|
147
|
+
// Missing required id
|
|
148
|
+
purposeIds: ['analytics'],
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
expect(validateOutput(invalidOutput)?.success).toBe(false);
|
|
153
|
+
|
|
154
|
+
const anotherInvalidOutput = {
|
|
155
|
+
isValid: true,
|
|
156
|
+
consent: {
|
|
157
|
+
id: 'consent-123',
|
|
158
|
+
// Missing required purposeIds
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
expect(validateOutput(anotherInvalidOutput)?.success).toBe(false);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('validates reasons as array of strings', () => {
|
|
166
|
+
const validOutput = {
|
|
167
|
+
isValid: false,
|
|
168
|
+
reasons: ['Reason 1', 'Reason 2'],
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
expect(validateOutput(validOutput)?.success).toBe(true);
|
|
172
|
+
|
|
173
|
+
const invalidOutput = {
|
|
174
|
+
isValid: false,
|
|
175
|
+
reasons: 'Single reason', // String instead of array
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
expect(validateOutput(invalidOutput)?.success).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Add required fields testing
|
|
184
|
+
tester.testRequiredFields('input', ['domain', 'type']);
|
|
185
|
+
tester.testRequiredFields('output', ['isValid']);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { PolicyTypeSchema } from '~/v2/db/schema';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Contract for the verify consent endpoint
|
|
7
|
+
* Verifies if a user has given consent for a specific policy
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Input schema based on VerifyConsentRequestBody
|
|
11
|
+
const verifyConsentInputSchema = z.strictObject({
|
|
12
|
+
subjectId: z.string().optional(),
|
|
13
|
+
externalSubjectId: z.string().optional(),
|
|
14
|
+
domain: z.string(),
|
|
15
|
+
type: PolicyTypeSchema,
|
|
16
|
+
policyId: z.string().optional(),
|
|
17
|
+
preferences: z.array(z.string()).optional(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Minimal consent schema based on the response interface
|
|
21
|
+
const consentSchema = z.looseObject({
|
|
22
|
+
id: z.string(),
|
|
23
|
+
purposeIds: z.array(z.string()),
|
|
24
|
+
}); // Allow additional properties
|
|
25
|
+
|
|
26
|
+
// Output schema based on VerifyConsentResponse
|
|
27
|
+
export const verifyConsentContract = oc
|
|
28
|
+
.route({
|
|
29
|
+
method: 'POST',
|
|
30
|
+
path: '/consent/verify',
|
|
31
|
+
description: `Verifies if a user has given valid consent for a specific policy and domain.
|
|
32
|
+
This endpoint performs comprehensive consent verification by:
|
|
33
|
+
|
|
34
|
+
1. Validating the subject's identity (using subjectId or externalSubjectId)
|
|
35
|
+
2. Verifying the domain's existence and validity
|
|
36
|
+
3. Checking if the specified policy exists and is active
|
|
37
|
+
4. Validating that all required purposes have been consented to
|
|
38
|
+
5. Ensuring the consent record is current and valid
|
|
39
|
+
|
|
40
|
+
The endpoint supports different types of consent verification:
|
|
41
|
+
- Cookie banner consent verification
|
|
42
|
+
- Privacy policy consent verification
|
|
43
|
+
- Terms and conditions verification
|
|
44
|
+
- Marketing communications consent verification
|
|
45
|
+
- Age verification
|
|
46
|
+
- Custom consent types
|
|
47
|
+
|
|
48
|
+
Use this endpoint to ensure compliance with privacy regulations and to verify user consent before processing personal data.`,
|
|
49
|
+
tags: ['consent'],
|
|
50
|
+
})
|
|
51
|
+
.errors({
|
|
52
|
+
// Input validation errors
|
|
53
|
+
INPUT_VALIDATION_FAILED: {
|
|
54
|
+
status: 422,
|
|
55
|
+
data: z.object({
|
|
56
|
+
formErrors: z.array(z.string()),
|
|
57
|
+
fieldErrors: z.record(z.string(), z.array(z.string()).optional()),
|
|
58
|
+
}),
|
|
59
|
+
error: 'Invalid input parameters',
|
|
60
|
+
},
|
|
61
|
+
// Subject errors
|
|
62
|
+
SUBJECT_NOT_FOUND: {
|
|
63
|
+
status: 404,
|
|
64
|
+
data: z.object({
|
|
65
|
+
subjectId: z.string().optional(),
|
|
66
|
+
externalSubjectId: z.string().optional(),
|
|
67
|
+
}),
|
|
68
|
+
error: 'Subject not found',
|
|
69
|
+
},
|
|
70
|
+
// Domain errors
|
|
71
|
+
DOMAIN_NOT_FOUND: {
|
|
72
|
+
status: 404,
|
|
73
|
+
data: z.object({
|
|
74
|
+
domain: z.string(),
|
|
75
|
+
}),
|
|
76
|
+
error: 'Domain not found',
|
|
77
|
+
},
|
|
78
|
+
// Policy errors
|
|
79
|
+
POLICY_NOT_FOUND: {
|
|
80
|
+
status: 404,
|
|
81
|
+
data: z.object({
|
|
82
|
+
policyId: z.string(),
|
|
83
|
+
type: z.string(),
|
|
84
|
+
}),
|
|
85
|
+
error: 'Policy not found or invalid',
|
|
86
|
+
},
|
|
87
|
+
// Purpose errors
|
|
88
|
+
PURPOSES_NOT_FOUND: {
|
|
89
|
+
status: 404,
|
|
90
|
+
data: z.object({
|
|
91
|
+
preferences: z.array(z.string()),
|
|
92
|
+
foundPurposes: z.array(z.string()),
|
|
93
|
+
}),
|
|
94
|
+
error: 'Could not find all specified purposes',
|
|
95
|
+
},
|
|
96
|
+
// Cookie banner specific errors
|
|
97
|
+
COOKIE_BANNER_PREFERENCES_REQUIRED: {
|
|
98
|
+
status: 400,
|
|
99
|
+
data: z.object({
|
|
100
|
+
type: z.literal('cookie_banner'),
|
|
101
|
+
}),
|
|
102
|
+
error: 'Preferences are required for cookie banner consent',
|
|
103
|
+
},
|
|
104
|
+
// Consent errors
|
|
105
|
+
NO_CONSENT_FOUND: {
|
|
106
|
+
status: 404,
|
|
107
|
+
data: z.object({
|
|
108
|
+
policyId: z.string(),
|
|
109
|
+
subjectId: z.string(),
|
|
110
|
+
domainId: z.string(),
|
|
111
|
+
}),
|
|
112
|
+
error: 'No consent found for the given policy',
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
.input(verifyConsentInputSchema)
|
|
116
|
+
.output(
|
|
117
|
+
z.object({
|
|
118
|
+
isValid: z.boolean(),
|
|
119
|
+
reasons: z.array(z.string()).optional(),
|
|
120
|
+
consent: consentSchema.optional(),
|
|
121
|
+
})
|
|
122
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InferContractRouterInputs,
|
|
3
|
+
InferContractRouterOutputs,
|
|
4
|
+
} from '@orpc/contract';
|
|
5
|
+
import { implement } from '@orpc/server';
|
|
6
|
+
|
|
7
|
+
import { consentContracts } from './consent';
|
|
8
|
+
import { metaContracts } from './meta';
|
|
9
|
+
|
|
10
|
+
const config = {
|
|
11
|
+
consent: consentContracts,
|
|
12
|
+
meta: metaContracts,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { config as contracts };
|
|
16
|
+
|
|
17
|
+
export const os = implement(config);
|
|
18
|
+
|
|
19
|
+
export type ContractsOutputs = InferContractRouterOutputs<typeof config>;
|
|
20
|
+
export type ContractsInputs = InferContractRouterInputs<typeof config>;
|