@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,521 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
import { createContractTests } from '~/v2/contracts/test.utils';
|
|
5
|
+
import { PolicyTypeSchema } from '~/v2/db/schema';
|
|
6
|
+
|
|
7
|
+
import { postConsentContract } from './post.contract';
|
|
8
|
+
|
|
9
|
+
// Create base tests for the contract using the utility
|
|
10
|
+
const tester = createContractTests('Post Consent', postConsentContract);
|
|
11
|
+
|
|
12
|
+
// Keep the detailed custom tests to maintain existing coverage
|
|
13
|
+
describe('Post Consent Contract Custom Tests', () => {
|
|
14
|
+
// Helper to access schemas consistently throughout tests
|
|
15
|
+
const schemas = {
|
|
16
|
+
input: postConsentContract['~orpc'].inputSchema,
|
|
17
|
+
output: postConsentContract['~orpc'].outputSchema,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Helper functions for common test patterns
|
|
21
|
+
const validateInput = (input: unknown) => {
|
|
22
|
+
return schemas.input?.safeParse(input);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const validateOutput = (output: unknown) => {
|
|
26
|
+
return schemas.output?.safeParse(output);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
describe('Schema Structure', () => {
|
|
30
|
+
it('input schema requires a type discriminator', () => {
|
|
31
|
+
const result = validateInput({ domain: 'example.com' });
|
|
32
|
+
expect(result?.success).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('supports all defined policy types', () => {
|
|
36
|
+
const policyTypes = PolicyTypeSchema.options;
|
|
37
|
+
|
|
38
|
+
for (const type of policyTypes) {
|
|
39
|
+
const input = {
|
|
40
|
+
type,
|
|
41
|
+
domain: 'example.com',
|
|
42
|
+
...(type === 'cookie_banner' ? { preferences: { test: true } } : {}),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const result = validateInput(input);
|
|
46
|
+
expect(result?.success).toBe(true);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('Input Validation', () => {
|
|
52
|
+
describe('cookie_banner type', () => {
|
|
53
|
+
it('accepts valid input with preferences', () => {
|
|
54
|
+
const validInput = {
|
|
55
|
+
type: 'cookie_banner',
|
|
56
|
+
domain: 'example.com',
|
|
57
|
+
preferences: { analytics: true, marketing: false },
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
const result = validateInput(validInput);
|
|
61
|
+
expect(result?.success).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('rejects input without required preferences', () => {
|
|
65
|
+
const invalidInput = {
|
|
66
|
+
type: 'cookie_banner',
|
|
67
|
+
domain: 'example.com',
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
70
|
+
const result = validateInput(invalidInput);
|
|
71
|
+
if (!result) {
|
|
72
|
+
throw new Error('Result is undefined');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
expect(result.success).toBe(false);
|
|
76
|
+
if (!result.success) {
|
|
77
|
+
// Use optional chaining to safely access potentially undefined properties
|
|
78
|
+
expect(result.error.issues?.[0]?.path).toContain('preferences');
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('verifies boolean values in preferences', () => {
|
|
83
|
+
const invalidPreferences = {
|
|
84
|
+
type: 'cookie_banner',
|
|
85
|
+
domain: 'example.com',
|
|
86
|
+
preferences: { analytics: 'yes' }, // Should be boolean
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const result = validateInput(invalidPreferences);
|
|
90
|
+
if (!result) {
|
|
91
|
+
throw new Error('Result is undefined');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
expect(result.success).toBe(false);
|
|
95
|
+
if (!result.success) {
|
|
96
|
+
expect(result.error.issues?.[0]?.path).toContain('preferences');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('policy-based types', () => {
|
|
102
|
+
it('validates privacy_policy input', () => {
|
|
103
|
+
const validInput = {
|
|
104
|
+
type: 'privacy_policy',
|
|
105
|
+
domain: 'example.com',
|
|
106
|
+
policyId: 'policy-123',
|
|
107
|
+
} as const;
|
|
108
|
+
|
|
109
|
+
const result = validateInput(validInput);
|
|
110
|
+
expect(result?.success).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('validates dpa input', () => {
|
|
114
|
+
const validInput = {
|
|
115
|
+
type: 'dpa',
|
|
116
|
+
domain: 'example.com',
|
|
117
|
+
policyId: 'dpa-123',
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result = validateInput(validInput);
|
|
121
|
+
expect(result?.success).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('validates terms_and_conditions input', () => {
|
|
125
|
+
const validInput = {
|
|
126
|
+
type: 'terms_and_conditions',
|
|
127
|
+
domain: 'example.com',
|
|
128
|
+
policyId: 'terms-123',
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const result = validateInput(validInput);
|
|
132
|
+
expect(result?.success).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('accepts optional preferences for policy-based consents', () => {
|
|
136
|
+
const validInput = {
|
|
137
|
+
type: 'privacy_policy',
|
|
138
|
+
domain: 'example.com',
|
|
139
|
+
policyId: 'policy-123',
|
|
140
|
+
preferences: { acceptAll: true, marketing: false },
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const result = validateInput(validInput);
|
|
144
|
+
expect(result?.success).toBe(true);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('other consent types', () => {
|
|
149
|
+
it('validates marketing_communications input', () => {
|
|
150
|
+
const validInput = {
|
|
151
|
+
type: 'marketing_communications',
|
|
152
|
+
domain: 'example.com',
|
|
153
|
+
subjectId: 'user-123',
|
|
154
|
+
} as const;
|
|
155
|
+
|
|
156
|
+
const result = validateInput(validInput);
|
|
157
|
+
if (!result) {
|
|
158
|
+
throw new Error('Result is undefined');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
expect(result.success).toBe(true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('validates age_verification input', () => {
|
|
165
|
+
const validInput = {
|
|
166
|
+
type: 'age_verification',
|
|
167
|
+
domain: 'example.com',
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const result = validateInput(validInput);
|
|
171
|
+
expect(result?.success).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('validates other type input', () => {
|
|
175
|
+
const validInput = {
|
|
176
|
+
type: 'other',
|
|
177
|
+
domain: 'example.com',
|
|
178
|
+
metadata: { customField: 'value' },
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const result = validateInput(validInput);
|
|
182
|
+
expect(result?.success).toBe(true);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('common requirements', () => {
|
|
187
|
+
it('rejects input with invalid type', () => {
|
|
188
|
+
const invalidInput = {
|
|
189
|
+
// Type cast to bypass TS errors for testing
|
|
190
|
+
type: 'invalid_type' as unknown as z.infer<typeof PolicyTypeSchema>,
|
|
191
|
+
domain: 'example.com',
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const result = validateInput(invalidInput);
|
|
195
|
+
|
|
196
|
+
if (!result) {
|
|
197
|
+
throw new Error('Result is undefined');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
expect(result.success).toBe(false);
|
|
201
|
+
if (!result.success) {
|
|
202
|
+
expect(result.error.issues?.[0]?.path).toContain('type');
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('requires domain field', () => {
|
|
207
|
+
const invalidInput = {
|
|
208
|
+
type: 'marketing_communications' as z.infer<typeof PolicyTypeSchema>,
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const result = validateInput(invalidInput);
|
|
212
|
+
if (!result) {
|
|
213
|
+
throw new Error('Result is undefined');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
expect(result.success).toBe(false);
|
|
217
|
+
if (!result.success) {
|
|
218
|
+
expect(result.error.issues?.[0]?.path).toContain('domain');
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('accepts additional metadata', () => {
|
|
223
|
+
const validInput = {
|
|
224
|
+
type: 'marketing_communications',
|
|
225
|
+
domain: 'example.com',
|
|
226
|
+
metadata: {
|
|
227
|
+
source: 'web',
|
|
228
|
+
campaign: 'summer2023',
|
|
229
|
+
customData: { nested: true },
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const result = validateInput(validInput);
|
|
234
|
+
expect(result?.success).toBe(true);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('accepts optional subjectId', () => {
|
|
238
|
+
const validInput = {
|
|
239
|
+
type: 'privacy_policy',
|
|
240
|
+
domain: 'example.com',
|
|
241
|
+
subjectId: 'user-abc-123',
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const result = validateInput(validInput);
|
|
245
|
+
expect(result?.success).toBe(true);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('accepts optional externalSubjectId', () => {
|
|
249
|
+
const validInput = {
|
|
250
|
+
type: 'privacy_policy',
|
|
251
|
+
domain: 'example.com',
|
|
252
|
+
externalSubjectId: 'external-user-123',
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const result = validateInput(validInput);
|
|
256
|
+
expect(result?.success).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe('Output Validation', () => {
|
|
262
|
+
it('validates complete output object', () => {
|
|
263
|
+
const validOutput = {
|
|
264
|
+
id: '123',
|
|
265
|
+
domainId: '456',
|
|
266
|
+
domain: 'example.com',
|
|
267
|
+
type: 'marketing_communications',
|
|
268
|
+
status: 'granted',
|
|
269
|
+
recordId: '789',
|
|
270
|
+
givenAt: new Date(),
|
|
271
|
+
metadata: { source: 'web' },
|
|
272
|
+
} as const;
|
|
273
|
+
|
|
274
|
+
const result = validateOutput(validOutput);
|
|
275
|
+
if (!result) {
|
|
276
|
+
throw new Error('Result is undefined');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
expect(result.success).toBe(true);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('rejects output without required fields', () => {
|
|
283
|
+
const invalidOutput = {
|
|
284
|
+
id: '123',
|
|
285
|
+
domain: 'example.com',
|
|
286
|
+
type: 'marketing_communications',
|
|
287
|
+
// Missing required fields: domainId, status, recordId, givenAt
|
|
288
|
+
} as const;
|
|
289
|
+
|
|
290
|
+
const result = validateOutput(invalidOutput);
|
|
291
|
+
if (!result) {
|
|
292
|
+
throw new Error('Result is undefined');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
expect(result.success).toBe(false);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('validates output with all possible status values', () => {
|
|
299
|
+
const statusValues = ['granted', 'denied', 'pending', 'withdrawn'];
|
|
300
|
+
|
|
301
|
+
for (const status of statusValues) {
|
|
302
|
+
const output = {
|
|
303
|
+
id: '123',
|
|
304
|
+
domainId: '456',
|
|
305
|
+
domain: 'example.com',
|
|
306
|
+
type: 'marketing_communications',
|
|
307
|
+
status,
|
|
308
|
+
recordId: '789',
|
|
309
|
+
givenAt: new Date(),
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const result = validateOutput(output);
|
|
313
|
+
expect(result?.success).toBe(true);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('validates output with different policy types', () => {
|
|
318
|
+
const policyTypes = PolicyTypeSchema.options;
|
|
319
|
+
|
|
320
|
+
for (const type of policyTypes) {
|
|
321
|
+
const output = {
|
|
322
|
+
id: '123',
|
|
323
|
+
domainId: '456',
|
|
324
|
+
domain: 'example.com',
|
|
325
|
+
type,
|
|
326
|
+
status: 'granted',
|
|
327
|
+
recordId: '789',
|
|
328
|
+
givenAt: new Date(),
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const result = validateOutput(output);
|
|
332
|
+
expect(result?.success).toBe(true);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe('givenAt field', () => {
|
|
337
|
+
it('rejects string values', () => {
|
|
338
|
+
const invalidOutput = {
|
|
339
|
+
id: '123',
|
|
340
|
+
domainId: '456',
|
|
341
|
+
domain: 'example.com',
|
|
342
|
+
type: 'marketing_communications',
|
|
343
|
+
status: 'granted',
|
|
344
|
+
recordId: '789',
|
|
345
|
+
givenAt: 'not-a-date', // This should now fail with z.date()
|
|
346
|
+
metadata: {},
|
|
347
|
+
} as const;
|
|
348
|
+
|
|
349
|
+
const result = validateOutput(invalidOutput);
|
|
350
|
+
if (!result) {
|
|
351
|
+
throw new Error('Result is undefined');
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
expect(result.success).toBe(false);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('accepts Date objects', () => {
|
|
358
|
+
const validOutput = {
|
|
359
|
+
id: '123',
|
|
360
|
+
domainId: '456',
|
|
361
|
+
domain: 'example.com',
|
|
362
|
+
type: 'marketing_communications',
|
|
363
|
+
status: 'granted',
|
|
364
|
+
recordId: '789',
|
|
365
|
+
givenAt: new Date(),
|
|
366
|
+
metadata: {},
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const result = validateOutput(validOutput);
|
|
370
|
+
expect(result?.success).toBe(true);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('rejects non-date values', () => {
|
|
374
|
+
const invalidOutput = {
|
|
375
|
+
id: '123',
|
|
376
|
+
domainId: '456',
|
|
377
|
+
domain: 'example.com',
|
|
378
|
+
type: 'marketing_communications',
|
|
379
|
+
status: 'granted',
|
|
380
|
+
recordId: '789',
|
|
381
|
+
givenAt: 123, // Number instead of Date
|
|
382
|
+
metadata: {},
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const result = validateOutput(invalidOutput);
|
|
386
|
+
expect(result?.success).toBe(false);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('accepts ISO date strings', () => {
|
|
390
|
+
const validOutput = {
|
|
391
|
+
id: '123',
|
|
392
|
+
domainId: '456',
|
|
393
|
+
domain: 'example.com',
|
|
394
|
+
type: 'marketing_communications',
|
|
395
|
+
status: 'granted',
|
|
396
|
+
recordId: '789',
|
|
397
|
+
givenAt: new Date(),
|
|
398
|
+
metadata: {},
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
const result = validateOutput(validOutput);
|
|
402
|
+
expect(result?.success).toBe(true);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('rejects non-string values', () => {
|
|
406
|
+
// Create an object with a number for givenAt (should fail validation)
|
|
407
|
+
const invalidOutput = {
|
|
408
|
+
id: '123',
|
|
409
|
+
domainId: '456',
|
|
410
|
+
domain: 'example.com',
|
|
411
|
+
type: 'marketing_communications',
|
|
412
|
+
status: 'granted',
|
|
413
|
+
recordId: '789',
|
|
414
|
+
givenAt: 123, // Number instead of string (intentionally invalid)
|
|
415
|
+
metadata: {},
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// We need to cast here because TypeScript wouldn't allow this invalid type normally
|
|
419
|
+
const result = validateOutput(invalidOutput);
|
|
420
|
+
if (!result) {
|
|
421
|
+
throw new Error('Result is undefined');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
expect(result.success).toBe(false);
|
|
425
|
+
if (!result.success) {
|
|
426
|
+
expect(result.error.issues?.[0]?.path).toContain('givenAt');
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
describe('Optional fields validation', () => {
|
|
432
|
+
it('accepts output without optional fields', () => {
|
|
433
|
+
const validOutput = {
|
|
434
|
+
id: '123',
|
|
435
|
+
domainId: '456',
|
|
436
|
+
domain: 'example.com',
|
|
437
|
+
type: 'marketing_communications',
|
|
438
|
+
status: 'granted',
|
|
439
|
+
recordId: '789',
|
|
440
|
+
givenAt: new Date(),
|
|
441
|
+
// No metadata, subjectId or externalSubjectId
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const result = validateOutput(validOutput);
|
|
445
|
+
expect(result?.success).toBe(true);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('accepts output with optional subjectId', () => {
|
|
449
|
+
const validOutput = {
|
|
450
|
+
id: '123',
|
|
451
|
+
domainId: '456',
|
|
452
|
+
domain: 'example.com',
|
|
453
|
+
type: 'marketing_communications',
|
|
454
|
+
status: 'granted',
|
|
455
|
+
recordId: '789',
|
|
456
|
+
givenAt: new Date(),
|
|
457
|
+
subjectId: 'user-123',
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const result = validateOutput(validOutput);
|
|
461
|
+
expect(result?.success).toBe(true);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it('accepts output with optional externalSubjectId', () => {
|
|
465
|
+
const validOutput = {
|
|
466
|
+
id: '123',
|
|
467
|
+
domainId: '456',
|
|
468
|
+
domain: 'example.com',
|
|
469
|
+
type: 'marketing_communications',
|
|
470
|
+
status: 'granted',
|
|
471
|
+
recordId: '789',
|
|
472
|
+
givenAt: new Date(),
|
|
473
|
+
externalSubjectId: 'external-user-123',
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
const result = validateOutput(validOutput);
|
|
477
|
+
expect(result?.success).toBe(true);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
it('accepts output with complex metadata', () => {
|
|
481
|
+
const validOutput = {
|
|
482
|
+
id: '123',
|
|
483
|
+
domainId: '456',
|
|
484
|
+
domain: 'example.com',
|
|
485
|
+
type: 'marketing_communications',
|
|
486
|
+
status: 'granted',
|
|
487
|
+
recordId: '789',
|
|
488
|
+
givenAt: new Date(),
|
|
489
|
+
metadata: {
|
|
490
|
+
source: 'web',
|
|
491
|
+
platform: 'mobile',
|
|
492
|
+
browser: { name: 'Chrome', version: '115' },
|
|
493
|
+
consentMethod: 'explicit',
|
|
494
|
+
nestedData: {
|
|
495
|
+
level1: {
|
|
496
|
+
level2: {
|
|
497
|
+
level3: true,
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
const result = validateOutput(validOutput);
|
|
505
|
+
expect(result?.success).toBe(true);
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
// Add required fields testing using the utility
|
|
512
|
+
tester.testRequiredFields('input', ['domain', 'type']);
|
|
513
|
+
tester.testRequiredFields('output', [
|
|
514
|
+
'id',
|
|
515
|
+
'domainId',
|
|
516
|
+
'domain',
|
|
517
|
+
'type',
|
|
518
|
+
'status',
|
|
519
|
+
'recordId',
|
|
520
|
+
'givenAt',
|
|
521
|
+
]);
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
import { PolicyTypeSchema } from '~/v2/db/schema';
|
|
5
|
+
|
|
6
|
+
const baseConsentSchema = z.object({
|
|
7
|
+
subjectId: z.string().optional(),
|
|
8
|
+
externalSubjectId: z.string().optional(),
|
|
9
|
+
domain: z.string(),
|
|
10
|
+
type: PolicyTypeSchema,
|
|
11
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
// Cookie banner needs preferences
|
|
15
|
+
const cookieBannerSchema = baseConsentSchema.extend({
|
|
16
|
+
type: z.literal('cookie_banner'),
|
|
17
|
+
preferences: z.record(z.string(), z.boolean()),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Policy based consent just needs the policy ID
|
|
21
|
+
const policyBasedSchema = baseConsentSchema.extend({
|
|
22
|
+
type: z.enum(['privacy_policy', 'dpa', 'terms_and_conditions']),
|
|
23
|
+
policyId: z.string().optional(),
|
|
24
|
+
preferences: z.record(z.string(), z.boolean()).optional(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Other consent types just need the base fields
|
|
28
|
+
const otherConsentSchema = baseConsentSchema.extend({
|
|
29
|
+
type: z.enum(['marketing_communications', 'age_verification', 'other']),
|
|
30
|
+
preferences: z.record(z.string(), z.boolean()).optional(),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const postConsentContract = oc
|
|
34
|
+
.route({
|
|
35
|
+
method: 'POST',
|
|
36
|
+
path: '/consent/set',
|
|
37
|
+
description: `Records a user's consent preferences and creates necessary consent records.
|
|
38
|
+
This endpoint handles various types of consent submissions:
|
|
39
|
+
|
|
40
|
+
1. Cookie Banner Consent:
|
|
41
|
+
- Records granular cookie preferences
|
|
42
|
+
- Supports multiple consent purposes
|
|
43
|
+
- Creates audit trail for compliance
|
|
44
|
+
|
|
45
|
+
2. Policy-Based Consent:
|
|
46
|
+
- Privacy Policy acceptance
|
|
47
|
+
- Data Processing Agreement (DPA) consent
|
|
48
|
+
- Terms and Conditions acceptance
|
|
49
|
+
- Links consent to specific policy versions
|
|
50
|
+
|
|
51
|
+
3. Other Consent Types:
|
|
52
|
+
- Marketing communications preferences
|
|
53
|
+
- Age verification consent
|
|
54
|
+
- Custom consent types
|
|
55
|
+
|
|
56
|
+
The endpoint performs the following operations:
|
|
57
|
+
- Creates or retrieves subject records
|
|
58
|
+
- Validates domain and policy information
|
|
59
|
+
- Creates consent records with audit trails
|
|
60
|
+
- Records consent purposes and preferences
|
|
61
|
+
- Generates audit logs for compliance
|
|
62
|
+
|
|
63
|
+
Use this endpoint to record user consent and maintain a compliant consent management system.`,
|
|
64
|
+
tags: ['consent', 'cookie-banner'],
|
|
65
|
+
})
|
|
66
|
+
.errors({
|
|
67
|
+
// Input validation errors
|
|
68
|
+
INPUT_VALIDATION_FAILED: {
|
|
69
|
+
status: 422,
|
|
70
|
+
data: z.object({
|
|
71
|
+
formErrors: z.array(z.string()),
|
|
72
|
+
fieldErrors: z.record(z.string(), z.array(z.string())),
|
|
73
|
+
}),
|
|
74
|
+
error: 'Invalid input parameters',
|
|
75
|
+
},
|
|
76
|
+
// Subject errors
|
|
77
|
+
SUBJECT_CREATION_FAILED: {
|
|
78
|
+
status: 400,
|
|
79
|
+
data: z.object({
|
|
80
|
+
subjectId: z.string().optional(),
|
|
81
|
+
externalSubjectId: z.string().optional(),
|
|
82
|
+
}),
|
|
83
|
+
error: 'Failed to create or find subject',
|
|
84
|
+
},
|
|
85
|
+
// Domain errors
|
|
86
|
+
DOMAIN_CREATION_FAILED: {
|
|
87
|
+
status: 500,
|
|
88
|
+
data: z.object({
|
|
89
|
+
domain: z.string(),
|
|
90
|
+
}),
|
|
91
|
+
error: 'Failed to create or find domain',
|
|
92
|
+
},
|
|
93
|
+
// Policy errors
|
|
94
|
+
POLICY_NOT_FOUND: {
|
|
95
|
+
status: 404,
|
|
96
|
+
data: z.object({
|
|
97
|
+
policyId: z.string(),
|
|
98
|
+
type: z.string(),
|
|
99
|
+
}),
|
|
100
|
+
error: 'Policy not found',
|
|
101
|
+
},
|
|
102
|
+
POLICY_INACTIVE: {
|
|
103
|
+
status: 409,
|
|
104
|
+
data: z.object({
|
|
105
|
+
policyId: z.string(),
|
|
106
|
+
type: z.string(),
|
|
107
|
+
}),
|
|
108
|
+
error: 'Policy is not active',
|
|
109
|
+
},
|
|
110
|
+
POLICY_CREATION_FAILED: {
|
|
111
|
+
status: 500,
|
|
112
|
+
data: z.object({
|
|
113
|
+
type: z.string(),
|
|
114
|
+
}),
|
|
115
|
+
error: 'Failed to create or find policy',
|
|
116
|
+
},
|
|
117
|
+
// Purpose errors
|
|
118
|
+
PURPOSE_CREATION_FAILED: {
|
|
119
|
+
status: 500,
|
|
120
|
+
data: z.object({
|
|
121
|
+
purposeCode: z.string(),
|
|
122
|
+
}),
|
|
123
|
+
error: 'Failed to create consent purpose',
|
|
124
|
+
},
|
|
125
|
+
// Transaction errors
|
|
126
|
+
CONSENT_CREATION_FAILED: {
|
|
127
|
+
status: 500,
|
|
128
|
+
data: z.object({
|
|
129
|
+
subjectId: z.string(),
|
|
130
|
+
domain: z.string(),
|
|
131
|
+
}),
|
|
132
|
+
error: 'Failed to create consent record',
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
.input(
|
|
136
|
+
z.discriminatedUnion('type', [
|
|
137
|
+
cookieBannerSchema,
|
|
138
|
+
policyBasedSchema,
|
|
139
|
+
otherConsentSchema,
|
|
140
|
+
])
|
|
141
|
+
)
|
|
142
|
+
.output(
|
|
143
|
+
z.object({
|
|
144
|
+
id: z.string(),
|
|
145
|
+
subjectId: z.string().optional(),
|
|
146
|
+
externalSubjectId: z.string().optional(),
|
|
147
|
+
domainId: z.string(),
|
|
148
|
+
domain: z.string(),
|
|
149
|
+
type: PolicyTypeSchema,
|
|
150
|
+
status: z.string(),
|
|
151
|
+
recordId: z.string(),
|
|
152
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
153
|
+
givenAt: z.date(),
|
|
154
|
+
})
|
|
155
|
+
);
|