@c15t/backend 0.0.1-rc.10
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 +11 -0
- package/.turbo/turbo-check-types.log +5 -0
- package/.turbo/turbo-fmt.log +7 -0
- package/.turbo/turbo-lint.log +6 -0
- package/.turbo/turbo-test.log +26 -0
- package/README-next.md +223 -0
- package/README.md +164 -0
- package/dist/api/call.d.ts +176 -0
- package/dist/api/call.d.ts.map +1 -0
- package/dist/api/index.d.ts +935 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/middlewares/index.d.ts +39 -0
- package/dist/api/middlewares/index.d.ts.map +1 -0
- package/dist/api/middlewares/origin-check.d.ts +82 -0
- package/dist/api/middlewares/origin-check.d.ts.map +1 -0
- package/dist/api/middlewares/validate-context.d.ts +38 -0
- package/dist/api/middlewares/validate-context.d.ts.map +1 -0
- package/dist/api/routes/__tests__/consent.test.d.ts +2 -0
- package/dist/api/routes/__tests__/consent.test.d.ts.map +1 -0
- package/dist/api/routes/__tests__/status.test.d.ts +2 -0
- package/dist/api/routes/__tests__/status.test.d.ts.map +1 -0
- package/dist/api/routes/error.d.ts +57 -0
- package/dist/api/routes/error.d.ts.map +1 -0
- package/dist/api/routes/generate-consent-receipt.d.ts +130 -0
- package/dist/api/routes/generate-consent-receipt.d.ts.map +1 -0
- package/dist/api/routes/get-consent-history.d.ts +133 -0
- package/dist/api/routes/get-consent-history.d.ts.map +1 -0
- package/dist/api/routes/get-consent-policy.d.ts +164 -0
- package/dist/api/routes/get-consent-policy.d.ts.map +1 -0
- package/dist/api/routes/get-consent.d.ts +148 -0
- package/dist/api/routes/get-consent.d.ts.map +1 -0
- package/dist/api/routes/index.d.ts +339 -0
- package/dist/api/routes/index.d.ts.map +1 -0
- package/dist/api/routes/ok.d.ts +87 -0
- package/dist/api/routes/ok.d.ts.map +1 -0
- package/dist/api/routes/set-consent.d.ts +245 -0
- package/dist/api/routes/set-consent.d.ts.map +1 -0
- package/dist/api/routes/show-consent-banner.d.ts +127 -0
- package/dist/api/routes/show-consent-banner.d.ts.map +1 -0
- package/dist/api/routes/status.d.ts +61 -0
- package/dist/api/routes/status.d.ts.map +1 -0
- package/dist/api/routes/verify-consent.d.ts +179 -0
- package/dist/api/routes/verify-consent.d.ts.map +1 -0
- package/dist/api/routes/withdraw-consent.d.ts +194 -0
- package/dist/api/routes/withdraw-consent.d.ts.map +1 -0
- package/dist/api/to-endpoints.d.ts +35 -0
- package/dist/api/to-endpoints.d.ts.map +1 -0
- package/dist/client/index.cjs +139 -0
- package/dist/client/index.d.ts +203 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +106 -0
- package/dist/client/types.d.ts +431 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/core.d.ts +124 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.test.d.ts +2 -0
- package/dist/core.test.d.ts.map +1 -0
- package/dist/db/adapters/drizzle-adapter/drizzle-adapter.d.ts +122 -0
- package/dist/db/adapters/drizzle-adapter/drizzle-adapter.d.ts.map +1 -0
- package/dist/db/adapters/drizzle-adapter/index.d.ts +2 -0
- package/dist/db/adapters/drizzle-adapter/index.d.ts.map +1 -0
- package/dist/db/adapters/drizzle.cjs +1531 -0
- package/dist/db/adapters/drizzle.js +1489 -0
- package/dist/db/adapters/kysely-adapter/dialect.d.ts +72 -0
- package/dist/db/adapters/kysely-adapter/dialect.d.ts.map +1 -0
- package/dist/db/adapters/kysely-adapter/index.d.ts +4 -0
- package/dist/db/adapters/kysely-adapter/index.d.ts.map +1 -0
- package/dist/db/adapters/kysely-adapter/kysely-adapter.d.ts +98 -0
- package/dist/db/adapters/kysely-adapter/kysely-adapter.d.ts.map +1 -0
- package/dist/db/adapters/kysely-adapter/types.d.ts +281 -0
- package/dist/db/adapters/kysely-adapter/types.d.ts.map +1 -0
- package/dist/db/adapters/kysely.cjs +1551 -0
- package/dist/db/adapters/kysely.js +1508 -0
- package/dist/db/adapters/memory-adapter/index.d.ts +2 -0
- package/dist/db/adapters/memory-adapter/index.d.ts.map +1 -0
- package/dist/db/adapters/memory-adapter/memory-adapter.d.ts +56 -0
- package/dist/db/adapters/memory-adapter/memory-adapter.d.ts.map +1 -0
- package/dist/db/adapters/memory.cjs +1391 -0
- package/dist/db/adapters/memory.js +1349 -0
- package/dist/db/adapters/prisma-adapter/index.d.ts +2 -0
- package/dist/db/adapters/prisma-adapter/index.d.ts.map +1 -0
- package/dist/db/adapters/prisma-adapter/prisma-adapter.d.ts +143 -0
- package/dist/db/adapters/prisma-adapter/prisma-adapter.d.ts.map +1 -0
- package/dist/db/adapters/prisma.cjs +1503 -0
- package/dist/db/adapters/prisma.js +1461 -0
- package/dist/db/adapters/types.d.ts +154 -0
- package/dist/db/adapters/types.d.ts.map +1 -0
- package/dist/db/adapters/utils.d.ts +36 -0
- package/dist/db/adapters/utils.d.ts.map +1 -0
- package/dist/db/core/fields/field-factory.d.ts +383 -0
- package/dist/db/core/fields/field-factory.d.ts.map +1 -0
- package/dist/db/core/fields/field-inference.d.ts +218 -0
- package/dist/db/core/fields/field-inference.d.ts.map +1 -0
- package/dist/db/core/fields/field-options-integration.d.ts +90 -0
- package/dist/db/core/fields/field-options-integration.d.ts.map +1 -0
- package/dist/db/core/fields/field-types.d.ts +182 -0
- package/dist/db/core/fields/field-types.d.ts.map +1 -0
- package/dist/db/core/fields/id-generator.d.ts +19 -0
- package/dist/db/core/fields/id-generator.d.ts.map +1 -0
- package/dist/db/core/fields/index.d.ts +8 -0
- package/dist/db/core/fields/index.d.ts.map +1 -0
- package/dist/db/core/fields/superjson-utils.d.ts +34 -0
- package/dist/db/core/fields/superjson-utils.d.ts.map +1 -0
- package/dist/db/core/fields/zod-fields.d.ts +1011 -0
- package/dist/db/core/fields/zod-fields.d.ts.map +1 -0
- package/dist/db/core/get-schema.d.ts +36 -0
- package/dist/db/core/get-schema.d.ts.map +1 -0
- package/dist/db/core/types.d.ts +41 -0
- package/dist/db/core/types.d.ts.map +1 -0
- package/dist/db/create-registry.d.ts +760 -0
- package/dist/db/create-registry.d.ts.map +1 -0
- package/dist/db/hooks/create-hooks.d.ts +32 -0
- package/dist/db/hooks/create-hooks.d.ts.map +1 -0
- package/dist/db/hooks/index.d.ts +40 -0
- package/dist/db/hooks/index.d.ts.map +1 -0
- package/dist/db/hooks/types.d.ts +133 -0
- package/dist/db/hooks/types.d.ts.map +1 -0
- package/dist/db/hooks/update-hooks.d.ts +33 -0
- package/dist/db/hooks/update-hooks.d.ts.map +1 -0
- package/dist/db/hooks/update-many-hooks.d.ts +55 -0
- package/dist/db/hooks/update-many-hooks.d.ts.map +1 -0
- package/dist/db/hooks/utils.d.ts +62 -0
- package/dist/db/hooks/utils.d.ts.map +1 -0
- package/dist/db/hooks/with-hooks-factory.d.ts +33 -0
- package/dist/db/hooks/with-hooks-factory.d.ts.map +1 -0
- package/dist/db/index.cjs +2458 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +2404 -0
- package/dist/db/migration/get-migration.d.ts +32 -0
- package/dist/db/migration/get-migration.d.ts.map +1 -0
- package/dist/db/migration/get-schema/get-schema.d.ts +27 -0
- package/dist/db/migration/get-schema/get-schema.d.ts.map +1 -0
- package/dist/db/migration/get-schema/index.d.ts +21 -0
- package/dist/db/migration/get-schema/index.d.ts.map +1 -0
- package/dist/db/migration/get-schema/process-fields.d.ts +16 -0
- package/dist/db/migration/get-schema/process-fields.d.ts.map +1 -0
- package/dist/db/migration/get-schema/process-tables.d.ts +13 -0
- package/dist/db/migration/get-schema/process-tables.d.ts.map +1 -0
- package/dist/db/migration/get-schema/types.d.ts +17 -0
- package/dist/db/migration/get-schema/types.d.ts.map +1 -0
- package/dist/db/migration/index.cjs +1613 -0
- package/dist/db/migration/index.d.ts +14 -0
- package/dist/db/migration/index.d.ts.map +1 -0
- package/dist/db/migration/index.js +1571 -0
- package/dist/db/migration/migration-builders.d.ts +28 -0
- package/dist/db/migration/migration-builders.d.ts.map +1 -0
- package/dist/db/migration/migration-execution.d.ts +12 -0
- package/dist/db/migration/migration-execution.d.ts.map +1 -0
- package/dist/db/migration/schema-comparison.d.ts +54 -0
- package/dist/db/migration/schema-comparison.d.ts.map +1 -0
- package/dist/db/migration/type-mapping.d.ts +86 -0
- package/dist/db/migration/type-mapping.d.ts.map +1 -0
- package/dist/db/migration/types.d.ts +37 -0
- package/dist/db/migration/types.d.ts.map +1 -0
- package/dist/db/schema/audit-log/index.d.ts +4 -0
- package/dist/db/schema/audit-log/index.d.ts.map +1 -0
- package/dist/db/schema/audit-log/registry.d.ts +128 -0
- package/dist/db/schema/audit-log/registry.d.ts.map +1 -0
- package/dist/db/schema/audit-log/schema.d.ts +67 -0
- package/dist/db/schema/audit-log/schema.d.ts.map +1 -0
- package/dist/db/schema/audit-log/table.d.ts +175 -0
- package/dist/db/schema/audit-log/table.d.ts.map +1 -0
- package/dist/db/schema/audit-log/types.d.ts +29 -0
- package/dist/db/schema/audit-log/types.d.ts.map +1 -0
- package/dist/db/schema/consent/index.d.ts +4 -0
- package/dist/db/schema/consent/index.d.ts.map +1 -0
- package/dist/db/schema/consent/registry.d.ts +318 -0
- package/dist/db/schema/consent/registry.d.ts.map +1 -0
- package/dist/db/schema/consent/schema.d.ts +135 -0
- package/dist/db/schema/consent/schema.d.ts.map +1 -0
- package/dist/db/schema/consent/table.d.ts +245 -0
- package/dist/db/schema/consent/table.d.ts.map +1 -0
- package/dist/db/schema/consent/types.d.ts +37 -0
- package/dist/db/schema/consent/types.d.ts.map +1 -0
- package/dist/db/schema/consent-geo-location/index.d.ts +4 -0
- package/dist/db/schema/consent-geo-location/index.d.ts.map +1 -0
- package/dist/db/schema/consent-geo-location/registry.d.ts +96 -0
- package/dist/db/schema/consent-geo-location/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-geo-location/schema.d.ts +71 -0
- package/dist/db/schema/consent-geo-location/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-geo-location/table.d.ts +167 -0
- package/dist/db/schema/consent-geo-location/table.d.ts.map +1 -0
- package/dist/db/schema/consent-geo-location/types.d.ts +21 -0
- package/dist/db/schema/consent-geo-location/types.d.ts.map +1 -0
- package/dist/db/schema/consent-policy/index.d.ts +4 -0
- package/dist/db/schema/consent-policy/index.d.ts.map +1 -0
- package/dist/db/schema/consent-policy/registry.d.ts +186 -0
- package/dist/db/schema/consent-policy/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-policy/schema.d.ts +68 -0
- package/dist/db/schema/consent-policy/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-policy/table.d.ts +147 -0
- package/dist/db/schema/consent-policy/table.d.ts.map +1 -0
- package/dist/db/schema/consent-policy/types.d.ts +28 -0
- package/dist/db/schema/consent-policy/types.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose/index.d.ts +4 -0
- package/dist/db/schema/consent-purpose/index.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose/registry.d.ts +136 -0
- package/dist/db/schema/consent-purpose/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose/schema.d.ts +79 -0
- package/dist/db/schema/consent-purpose/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose/table.d.ts +161 -0
- package/dist/db/schema/consent-purpose/table.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose/types.d.ts +16 -0
- package/dist/db/schema/consent-purpose/types.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose-junction/index.d.ts +4 -0
- package/dist/db/schema/consent-purpose-junction/index.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose-junction/registry.d.ts +109 -0
- package/dist/db/schema/consent-purpose-junction/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose-junction/schema.d.ts +57 -0
- package/dist/db/schema/consent-purpose-junction/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose-junction/table.d.ts +138 -0
- package/dist/db/schema/consent-purpose-junction/table.d.ts.map +1 -0
- package/dist/db/schema/consent-purpose-junction/types.d.ts +14 -0
- package/dist/db/schema/consent-purpose-junction/types.d.ts.map +1 -0
- package/dist/db/schema/consent-record/index.d.ts +4 -0
- package/dist/db/schema/consent-record/index.d.ts.map +1 -0
- package/dist/db/schema/consent-record/registry.d.ts +119 -0
- package/dist/db/schema/consent-record/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-record/schema.d.ts +57 -0
- package/dist/db/schema/consent-record/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-record/table.d.ts +123 -0
- package/dist/db/schema/consent-record/table.d.ts.map +1 -0
- package/dist/db/schema/consent-record/types.d.ts +21 -0
- package/dist/db/schema/consent-record/types.d.ts.map +1 -0
- package/dist/db/schema/consent-withdrawal/index.d.ts +4 -0
- package/dist/db/schema/consent-withdrawal/index.d.ts.map +1 -0
- package/dist/db/schema/consent-withdrawal/registry.d.ts +134 -0
- package/dist/db/schema/consent-withdrawal/registry.d.ts.map +1 -0
- package/dist/db/schema/consent-withdrawal/schema.d.ts +67 -0
- package/dist/db/schema/consent-withdrawal/schema.d.ts.map +1 -0
- package/dist/db/schema/consent-withdrawal/table.d.ts +170 -0
- package/dist/db/schema/consent-withdrawal/table.d.ts.map +1 -0
- package/dist/db/schema/consent-withdrawal/types.d.ts +28 -0
- package/dist/db/schema/consent-withdrawal/types.d.ts.map +1 -0
- package/dist/db/schema/definition.d.ts +1100 -0
- package/dist/db/schema/definition.d.ts.map +1 -0
- package/dist/db/schema/domain/index.d.ts +4 -0
- package/dist/db/schema/domain/index.d.ts.map +1 -0
- package/dist/db/schema/domain/registry.d.ts +169 -0
- package/dist/db/schema/domain/registry.d.ts.map +1 -0
- package/dist/db/schema/domain/schema.d.ts +60 -0
- package/dist/db/schema/domain/schema.d.ts.map +1 -0
- package/dist/db/schema/domain/table.d.ts +140 -0
- package/dist/db/schema/domain/table.d.ts.map +1 -0
- package/dist/db/schema/domain/types.d.ts +27 -0
- package/dist/db/schema/domain/types.d.ts.map +1 -0
- package/dist/db/schema/geo-location/index.d.ts +4 -0
- package/dist/db/schema/geo-location/index.d.ts.map +1 -0
- package/dist/db/schema/geo-location/registry.d.ts +114 -0
- package/dist/db/schema/geo-location/registry.d.ts.map +1 -0
- package/dist/db/schema/geo-location/schema.d.ts +58 -0
- package/dist/db/schema/geo-location/schema.d.ts.map +1 -0
- package/dist/db/schema/geo-location/table.d.ts +132 -0
- package/dist/db/schema/geo-location/table.d.ts.map +1 -0
- package/dist/db/schema/geo-location/types.d.ts +17 -0
- package/dist/db/schema/geo-location/types.d.ts.map +1 -0
- package/dist/db/schema/index.d.ts +85 -0
- package/dist/db/schema/index.d.ts.map +1 -0
- package/dist/db/schema/parser.d.ts +183 -0
- package/dist/db/schema/parser.d.ts.map +1 -0
- package/dist/db/schema/schemas.d.ts +383 -0
- package/dist/db/schema/schemas.d.ts.map +1 -0
- package/dist/db/schema/subject/index.d.ts +4 -0
- package/dist/db/schema/subject/index.d.ts.map +1 -0
- package/dist/db/schema/subject/registry.d.ts +141 -0
- package/dist/db/schema/subject/registry.d.ts.map +1 -0
- package/dist/db/schema/subject/schema.d.ts +56 -0
- package/dist/db/schema/subject/schema.d.ts.map +1 -0
- package/dist/db/schema/subject/table.d.ts +136 -0
- package/dist/db/schema/subject/table.d.ts.map +1 -0
- package/dist/db/schema/subject/types.d.ts +22 -0
- package/dist/db/schema/subject/types.d.ts.map +1 -0
- package/dist/db/schema/types.d.ts +136 -0
- package/dist/db/schema/types.d.ts.map +1 -0
- package/dist/db/utils/adapter-factory.d.ts +21 -0
- package/dist/db/utils/adapter-factory.d.ts.map +1 -0
- package/dist/db/utils/index.d.ts +10 -0
- package/dist/db/utils/index.d.ts.map +1 -0
- package/dist/db/utils.d.ts +4 -0
- package/dist/db/utils.d.ts.map +1 -0
- package/dist/error/codes.cjs +68 -0
- package/dist/error/codes.d.ts +175 -0
- package/dist/error/codes.d.ts.map +1 -0
- package/dist/error/codes.js +35 -0
- package/dist/error/error.d.ts +79 -0
- package/dist/error/error.d.ts.map +1 -0
- package/dist/error/index.cjs +172 -0
- package/dist/error/index.d.ts +9 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +129 -0
- package/dist/error/logging.d.ts +25 -0
- package/dist/error/logging.d.ts.map +1 -0
- package/dist/error/pipeline.d.ts +19 -0
- package/dist/error/pipeline.d.ts.map +1 -0
- package/dist/error/recovery.d.ts +22 -0
- package/dist/error/recovery.d.ts.map +1 -0
- package/dist/error/results.d.ts +56 -0
- package/dist/error/results.d.ts.map +1 -0
- package/dist/index.cjs +4777 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4708 -0
- package/dist/init.d.ts +52 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.test.d.ts +2 -0
- package/dist/init.test.d.ts.map +1 -0
- package/dist/integrations/index.cjs +281 -0
- package/dist/integrations/index.d.ts +7 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +248 -0
- package/dist/integrations/next.cjs +131 -0
- package/dist/integrations/next.d.ts +29 -0
- package/dist/integrations/next.d.ts.map +1 -0
- package/dist/integrations/next.js +99 -0
- package/dist/integrations/react.cjs +182 -0
- package/dist/integrations/react.d.ts +257 -0
- package/dist/integrations/react.d.ts.map +1 -0
- package/dist/integrations/react.js +150 -0
- package/dist/plugins/geo/index.d.ts +2 -0
- package/dist/plugins/geo/index.d.ts.map +1 -0
- package/dist/test/utils.d.ts +65 -0
- package/dist/test/utils.d.ts.map +1 -0
- package/dist/types/api.d.ts +89 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/context.d.ts +205 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/helper.d.ts +78 -0
- package/dist/types/helper.d.ts.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +0 -0
- package/dist/types/options.d.ts +172 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/plugins.d.ts +442 -0
- package/dist/types/plugins.d.ts.map +1 -0
- package/dist/utils/env.d.ts +77 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/hide-metadata.d.ts +22 -0
- package/dist/utils/hide-metadata.d.ts.map +1 -0
- package/dist/utils/index.cjs +268 -0
- package/dist/utils/index.d.ts +18 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +210 -0
- package/dist/utils/ip.d.ts +10 -0
- package/dist/utils/ip.d.ts.map +1 -0
- package/dist/utils/json.d.ts +14 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +108 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/url.d.ts +87 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/wildcard.d.ts +46 -0
- package/dist/utils/wildcard.d.ts.map +1 -0
- package/knip.json +37 -0
- package/package.json +146 -0
- package/rslib.config.ts +104 -0
- package/src/api/call.ts +177 -0
- package/src/api/index.ts +303 -0
- package/src/api/middlewares/index.ts +38 -0
- package/src/api/middlewares/origin-check.ts +260 -0
- package/src/api/middlewares/validate-context.ts +175 -0
- package/src/api/routes/__tests__/consent.test.ts +270 -0
- package/src/api/routes/__tests__/status.test.ts +36 -0
- package/src/api/routes/error.ts +130 -0
- package/src/api/routes/generate-consent-receipt.ts +244 -0
- package/src/api/routes/get-consent-history.ts +128 -0
- package/src/api/routes/get-consent-policy.ts +327 -0
- package/src/api/routes/get-consent.ts +230 -0
- package/src/api/routes/index.ts +12 -0
- package/src/api/routes/ok.ts +45 -0
- package/src/api/routes/set-consent.ts +328 -0
- package/src/api/routes/show-consent-banner.ts +149 -0
- package/src/api/routes/status.ts +62 -0
- package/src/api/routes/verify-consent.ts +272 -0
- package/src/api/routes/withdraw-consent.ts +293 -0
- package/src/api/to-endpoints.ts +371 -0
- package/src/client/index.ts +471 -0
- package/src/client/types.ts +458 -0
- package/src/core.test.ts +303 -0
- package/src/core.ts +267 -0
- package/src/db/adapters/drizzle-adapter/drizzle-adapter.ts +711 -0
- package/src/db/adapters/drizzle-adapter/index.ts +1 -0
- package/src/db/adapters/kysely-adapter/dialect.ts +192 -0
- package/src/db/adapters/kysely-adapter/index.ts +3 -0
- package/src/db/adapters/kysely-adapter/kysely-adapter.ts +1168 -0
- package/src/db/adapters/kysely-adapter/types.ts +307 -0
- package/src/db/adapters/memory-adapter/index.ts +1 -0
- package/src/db/adapters/memory-adapter/memory-adapter.ts +648 -0
- package/src/db/adapters/prisma-adapter/index.ts +1 -0
- package/src/db/adapters/prisma-adapter/prisma-adapter.ts +586 -0
- package/src/db/adapters/types.ts +203 -0
- package/src/db/adapters/utils.ts +51 -0
- package/src/db/core/fields/field-factory.ts +804 -0
- package/src/db/core/fields/field-inference.ts +298 -0
- package/src/db/core/fields/field-options-integration.ts +135 -0
- package/src/db/core/fields/field-types.ts +233 -0
- package/src/db/core/fields/id-generator.ts +57 -0
- package/src/db/core/fields/index.ts +56 -0
- package/src/db/core/fields/superjson-utils.ts +155 -0
- package/src/db/core/fields/zod-fields.ts +269 -0
- package/src/db/core/get-schema.ts +102 -0
- package/src/db/core/types.ts +52 -0
- package/src/db/create-registry.ts +31 -0
- package/src/db/hooks/create-hooks.ts +88 -0
- package/src/db/hooks/index.ts +39 -0
- package/src/db/hooks/types.ts +164 -0
- package/src/db/hooks/update-hooks.ts +91 -0
- package/src/db/hooks/update-many-hooks.ts +176 -0
- package/src/db/hooks/utils.ts +151 -0
- package/src/db/hooks/with-hooks-factory.ts +68 -0
- package/src/db/index.ts +32 -0
- package/src/db/migration/get-migration.ts +89 -0
- package/src/db/migration/get-schema/get-schema.ts +44 -0
- package/src/db/migration/get-schema/index.ts +20 -0
- package/src/db/migration/get-schema/process-fields.ts +66 -0
- package/src/db/migration/get-schema/process-tables.ts +68 -0
- package/src/db/migration/get-schema/types.ts +18 -0
- package/src/db/migration/index.ts +18 -0
- package/src/db/migration/migration-builders.ts +170 -0
- package/src/db/migration/migration-execution.ts +79 -0
- package/src/db/migration/schema-comparison.ts +216 -0
- package/src/db/migration/type-mapping.ts +255 -0
- package/src/db/migration/types.ts +46 -0
- package/src/db/schema/audit-log/index.ts +3 -0
- package/src/db/schema/audit-log/registry.ts +228 -0
- package/src/db/schema/audit-log/schema.ts +46 -0
- package/src/db/schema/audit-log/table.ts +185 -0
- package/src/db/schema/audit-log/types.ts +29 -0
- package/src/db/schema/consent/index.ts +3 -0
- package/src/db/schema/consent/registry.ts +381 -0
- package/src/db/schema/consent/schema.ts +65 -0
- package/src/db/schema/consent/table.ts +220 -0
- package/src/db/schema/consent/types.ts +39 -0
- package/src/db/schema/consent-geo-location/index.ts +3 -0
- package/src/db/schema/consent-geo-location/registry.ts +124 -0
- package/src/db/schema/consent-geo-location/schema.ts +51 -0
- package/src/db/schema/consent-geo-location/table.ts +169 -0
- package/src/db/schema/consent-geo-location/types.ts +21 -0
- package/src/db/schema/consent-policy/index.ts +3 -0
- package/src/db/schema/consent-policy/registry.ts +313 -0
- package/src/db/schema/consent-policy/schema.ts +47 -0
- package/src/db/schema/consent-policy/table.ts +141 -0
- package/src/db/schema/consent-policy/types.ts +28 -0
- package/src/db/schema/consent-purpose/index.ts +3 -0
- package/src/db/schema/consent-purpose/registry.ts +188 -0
- package/src/db/schema/consent-purpose/schema.ts +58 -0
- package/src/db/schema/consent-purpose/table.ts +154 -0
- package/src/db/schema/consent-purpose/types.ts +16 -0
- package/src/db/schema/consent-purpose-junction/index.ts +3 -0
- package/src/db/schema/consent-purpose-junction/registry.ts +189 -0
- package/src/db/schema/consent-purpose-junction/schema.ts +49 -0
- package/src/db/schema/consent-purpose-junction/table.ts +142 -0
- package/src/db/schema/consent-purpose-junction/types.ts +14 -0
- package/src/db/schema/consent-record/index.ts +3 -0
- package/src/db/schema/consent-record/registry.ts +209 -0
- package/src/db/schema/consent-record/schema.ts +42 -0
- package/src/db/schema/consent-record/table.ts +124 -0
- package/src/db/schema/consent-record/types.ts +21 -0
- package/src/db/schema/consent-withdrawal/index.ts +3 -0
- package/src/db/schema/consent-withdrawal/registry.ts +219 -0
- package/src/db/schema/consent-withdrawal/schema.ts +48 -0
- package/src/db/schema/consent-withdrawal/table.ts +181 -0
- package/src/db/schema/consent-withdrawal/types.ts +29 -0
- package/src/db/schema/definition.ts +196 -0
- package/src/db/schema/domain/index.ts +3 -0
- package/src/db/schema/domain/registry.ts +272 -0
- package/src/db/schema/domain/schema.ts +43 -0
- package/src/db/schema/domain/table.ts +137 -0
- package/src/db/schema/domain/types.ts +27 -0
- package/src/db/schema/geo-location/index.ts +3 -0
- package/src/db/schema/geo-location/registry.ts +159 -0
- package/src/db/schema/geo-location/schema.ts +45 -0
- package/src/db/schema/geo-location/table.ts +148 -0
- package/src/db/schema/geo-location/types.ts +18 -0
- package/src/db/schema/index.ts +96 -0
- package/src/db/schema/parser.ts +417 -0
- package/src/db/schema/schemas.ts +35 -0
- package/src/db/schema/subject/index.ts +3 -0
- package/src/db/schema/subject/registry.ts +371 -0
- package/src/db/schema/subject/schema.ts +41 -0
- package/src/db/schema/subject/table.ts +139 -0
- package/src/db/schema/subject/types.ts +22 -0
- package/src/db/schema/types.ts +154 -0
- package/src/db/utils/adapter-factory.ts +64 -0
- package/src/db/utils/index.ts +10 -0
- package/src/db/utils.ts +42 -0
- package/src/docs/ADVANCED_JSON_HANDLING.md +99 -0
- package/src/docs/neverthrow.md +171 -0
- package/src/error/codes.ts +201 -0
- package/src/error/error.ts +145 -0
- package/src/error/index.ts +23 -0
- package/src/error/logging.ts +52 -0
- package/src/error/pipeline.ts +57 -0
- package/src/error/recovery.ts +45 -0
- package/src/error/results.ts +100 -0
- package/src/index.ts +79 -0
- package/src/init.test.ts +235 -0
- package/src/init.ts +261 -0
- package/src/integrations/index.ts +10 -0
- package/src/integrations/next.ts +136 -0
- package/src/integrations/react.ts +567 -0
- package/src/plugins/geo/index.ts +563 -0
- package/src/test/utils.ts +244 -0
- package/src/types/api.ts +101 -0
- package/src/types/context.ts +235 -0
- package/src/types/helper.ts +87 -0
- package/src/types/index.ts +5 -0
- package/src/types/options.ts +189 -0
- package/src/types/plugins.ts +538 -0
- package/src/utils/env.ts +103 -0
- package/src/utils/hide-metadata.ts +21 -0
- package/src/utils/index.ts +17 -0
- package/src/utils/ip.ts +45 -0
- package/src/utils/json.ts +19 -0
- package/src/utils/logger.ts +252 -0
- package/src/utils/url.ts +194 -0
- package/src/utils/wildcard.ts +253 -0
- package/tsconfig.json +12 -0
- package/vitest.config.ts +14 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { BASE_ERROR_CODES, C15TError } from '~/error';
|
|
2
|
+
import type { GenericEndpointContext } from '~/types';
|
|
3
|
+
import { getHost, getOrigin, getProtocol } from '~/utils/url';
|
|
4
|
+
import { wildcardMatch } from '~/utils/wildcard';
|
|
5
|
+
import { createAuthMiddleware } from '../call';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Regular expression for validating relative URLs
|
|
9
|
+
* Ensures URLs don't contain path traversal attacks and have a valid structure
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
const VALID_RELATIVE_URL_REGEX =
|
|
14
|
+
/^\/(?!\/|\\|%2f|%5c)[\w\-./]*(?:\?[\w\-./=&%]*)?$/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Middleware that validates request origins and callback URLs against trusted origins
|
|
18
|
+
*
|
|
19
|
+
* This middleware performs security checks to prevent cross-site request forgery (CSRF)
|
|
20
|
+
* and open redirect vulnerabilities by validating various URLs in the request against
|
|
21
|
+
* a list of trusted origins configured in the C15T context.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* The middleware checks the following URLs from request body and headers:
|
|
25
|
+
* - Origin/Referer header (when cookies are used and CSRF checks are enabled)
|
|
26
|
+
* - callbackURL
|
|
27
|
+
* - redirectTo
|
|
28
|
+
* - errorCallbackURL
|
|
29
|
+
* - newSubjectCallbackURL
|
|
30
|
+
*
|
|
31
|
+
* URLs are validated using exact matching for origins and wildcard pattern matching
|
|
32
|
+
* for hostnames. Relative URLs are allowed for callback URLs but must match a safe
|
|
33
|
+
* URL pattern.
|
|
34
|
+
*
|
|
35
|
+
* @throws {C15TError} Throws a FORBIDDEN error if any URL fails validation
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { c15tInstance } from '@c15t/backend';
|
|
40
|
+
* // This middleware is typically used in router configuration
|
|
41
|
+
* const router = createRouter(endpoints, {
|
|
42
|
+
* routerMiddleware: [
|
|
43
|
+
* {
|
|
44
|
+
* path: '/**',
|
|
45
|
+
* middleware: originCheckMiddleware
|
|
46
|
+
* }
|
|
47
|
+
* ]
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* // To configure trusted origins in your C15T options:
|
|
51
|
+
* const c15t = c15tInstance({
|
|
52
|
+
* // Static list of trusted origins
|
|
53
|
+
* trustedOrigins: [
|
|
54
|
+
* 'https://example.com',
|
|
55
|
+
* 'https://*.example.org'
|
|
56
|
+
* ]
|
|
57
|
+
*
|
|
58
|
+
* // Or a function to dynamically determine trusted origins
|
|
59
|
+
* trustedOrigins: (request) => {
|
|
60
|
+
* const host = new URL(request.url).host;
|
|
61
|
+
* return [`https://${host}`, `http://${host}`];
|
|
62
|
+
* }
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export const originCheckMiddleware = createAuthMiddleware(async (ctx) => {
|
|
67
|
+
if (ctx.request?.method !== 'POST' || !ctx.request) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const { body, query, context } = ctx;
|
|
71
|
+
const originHeader =
|
|
72
|
+
ctx.headers?.get('origin') || ctx.headers?.get('referer') || '';
|
|
73
|
+
const callbackURL = body?.callbackURL || query?.callbackURL;
|
|
74
|
+
const redirectURL = body?.redirectTo;
|
|
75
|
+
const errorCallbackURL = body?.errorCallbackURL;
|
|
76
|
+
const newSubjectCallbackURL = body?.newSubjectCallbackURL;
|
|
77
|
+
const trustedOrigins: string[] = Array.isArray(context.options.trustedOrigins)
|
|
78
|
+
? context.trustedOrigins
|
|
79
|
+
: [
|
|
80
|
+
...context.trustedOrigins,
|
|
81
|
+
...(context.options.trustedOrigins?.(ctx.request) || []),
|
|
82
|
+
];
|
|
83
|
+
const usesCookies = ctx.headers?.has('cookie');
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Determines if a URL matches a trusted origin pattern
|
|
87
|
+
*
|
|
88
|
+
* @internal
|
|
89
|
+
* @param url - The URL to check
|
|
90
|
+
* @param pattern - The trusted origin pattern to match against
|
|
91
|
+
* @returns Whether the URL matches the pattern
|
|
92
|
+
*/
|
|
93
|
+
const matchesPattern = (url: string, pattern: string): boolean => {
|
|
94
|
+
if (url.startsWith('/')) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (pattern.includes('*')) {
|
|
98
|
+
return wildcardMatch(pattern)(getHost(url));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const protocol = getProtocol(url);
|
|
102
|
+
return protocol === 'http:' || protocol === 'https:' || !protocol
|
|
103
|
+
? pattern === getOrigin(url)
|
|
104
|
+
: url.startsWith(pattern);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Validates a URL against trusted origins
|
|
109
|
+
*
|
|
110
|
+
* @internal
|
|
111
|
+
* @param url - The URL to validate
|
|
112
|
+
* @param label - A label describing what type of URL is being validated
|
|
113
|
+
* @throws {C15TError} If the URL is not from a trusted origin
|
|
114
|
+
*/
|
|
115
|
+
const validateURL = (url: string | undefined, label: string) => {
|
|
116
|
+
if (!url) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const isTrustedOrigin = trustedOrigins.some(
|
|
120
|
+
(origin) =>
|
|
121
|
+
matchesPattern(url, origin) ||
|
|
122
|
+
(url?.startsWith('/') &&
|
|
123
|
+
label !== 'origin' &&
|
|
124
|
+
VALID_RELATIVE_URL_REGEX.test(url))
|
|
125
|
+
);
|
|
126
|
+
if (!isTrustedOrigin) {
|
|
127
|
+
ctx.context.logger.error(`Invalid ${label}: ${url}`);
|
|
128
|
+
ctx.context.logger.info(
|
|
129
|
+
`If it's a valid URL, please add ${url} to trustedOrigins in your auth config\n`,
|
|
130
|
+
`Current list of trustedOrigins: ${trustedOrigins}`
|
|
131
|
+
);
|
|
132
|
+
throw new C15TError(
|
|
133
|
+
'The URL provided is not from a trusted origin. Please ensure the URL is correctly configured in the trusted origins list.',
|
|
134
|
+
{
|
|
135
|
+
code: BASE_ERROR_CODES.FORBIDDEN,
|
|
136
|
+
status: 403,
|
|
137
|
+
data: {
|
|
138
|
+
url,
|
|
139
|
+
label,
|
|
140
|
+
trustedOrigins,
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
if (usesCookies && !ctx.context.options.advanced?.disableCSRFCheck) {
|
|
147
|
+
validateURL(originHeader, 'origin');
|
|
148
|
+
}
|
|
149
|
+
callbackURL && validateURL(callbackURL, 'callbackURL');
|
|
150
|
+
redirectURL && validateURL(redirectURL, 'redirectURL');
|
|
151
|
+
errorCallbackURL && validateURL(errorCallbackURL, 'errorCallbackURL');
|
|
152
|
+
newSubjectCallbackURL &&
|
|
153
|
+
validateURL(newSubjectCallbackURL, 'newSubjectCallbackURL');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Creates a middleware that validates a specific URL against trusted origins
|
|
158
|
+
*
|
|
159
|
+
* This factory function creates a middleware for validating a single URL extracted
|
|
160
|
+
* from the request context against the list of trusted origins.
|
|
161
|
+
*
|
|
162
|
+
* @param getValue - A function that extracts the URL to validate from the endpoint context
|
|
163
|
+
* @returns A middleware that validates the extracted URL
|
|
164
|
+
* @throws {C15TError} Throws a FORBIDDEN error if the URL fails validation
|
|
165
|
+
*
|
|
166
|
+
* @remarks
|
|
167
|
+
* Unlike the more comprehensive originCheckMiddleware, this factory allows creating
|
|
168
|
+
* targeted middleware for specific URL fields or custom extraction logic.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* // Create a middleware that validates the 'returnUrl' from request body
|
|
173
|
+
* const validateReturnUrl = originCheck(ctx => ctx.body?.returnUrl);
|
|
174
|
+
*
|
|
175
|
+
* // Use the middleware in a specific route
|
|
176
|
+
* router.post('/api/subscribe', validateReturnUrl, subscribeHandler);
|
|
177
|
+
*
|
|
178
|
+
* // Create a middleware that validates a URL from a custom header
|
|
179
|
+
* const validateHeaderUrl = originCheck(ctx =>
|
|
180
|
+
* ctx.headers?.get('x-callback-url')
|
|
181
|
+
* );
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export const originCheck = (
|
|
185
|
+
getValue: (ctx: GenericEndpointContext) => string
|
|
186
|
+
) =>
|
|
187
|
+
createAuthMiddleware(async (ctx) => {
|
|
188
|
+
if (!ctx.request) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const { context } = ctx;
|
|
192
|
+
const callbackURL = getValue(ctx);
|
|
193
|
+
const trustedOrigins: string[] = Array.isArray(
|
|
194
|
+
context.options.trustedOrigins
|
|
195
|
+
)
|
|
196
|
+
? context.trustedOrigins
|
|
197
|
+
: [
|
|
198
|
+
...context.trustedOrigins,
|
|
199
|
+
...(context.options.trustedOrigins?.(ctx.request) || []),
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Determines if a URL matches a trusted origin pattern
|
|
204
|
+
*
|
|
205
|
+
* @internal
|
|
206
|
+
* @param url - The URL to check
|
|
207
|
+
* @param pattern - The trusted origin pattern to match against
|
|
208
|
+
* @returns Whether the URL matches the pattern
|
|
209
|
+
*/
|
|
210
|
+
const matchesPattern = (url: string, pattern: string): boolean => {
|
|
211
|
+
if (url.startsWith('/')) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
if (pattern.includes('*')) {
|
|
215
|
+
return wildcardMatch(pattern)(getHost(url));
|
|
216
|
+
}
|
|
217
|
+
return url.startsWith(pattern);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Validates a URL against trusted origins
|
|
222
|
+
*
|
|
223
|
+
* @internal
|
|
224
|
+
* @param url - The URL to validate
|
|
225
|
+
* @param label - A label describing what type of URL is being validated
|
|
226
|
+
* @throws {C15TError} If the URL is not from a trusted origin
|
|
227
|
+
*/
|
|
228
|
+
const validateURL = (url: string | undefined, label: string) => {
|
|
229
|
+
if (!url) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const isTrustedOrigin = trustedOrigins.some(
|
|
233
|
+
(origin) =>
|
|
234
|
+
matchesPattern(url, origin) ||
|
|
235
|
+
(url?.startsWith('/') &&
|
|
236
|
+
label !== 'origin' &&
|
|
237
|
+
VALID_RELATIVE_URL_REGEX.test(url))
|
|
238
|
+
);
|
|
239
|
+
if (!isTrustedOrigin) {
|
|
240
|
+
ctx.context.logger.error(`Invalid ${label}: ${url}`);
|
|
241
|
+
ctx.context.logger.info(
|
|
242
|
+
`If it's a valid URL, please add ${url} to trustedOrigins in your auth config\n`,
|
|
243
|
+
`Current list of trustedOrigins: ${trustedOrigins}`
|
|
244
|
+
);
|
|
245
|
+
throw new C15TError(
|
|
246
|
+
'The URL provided is not from a trusted origin. Please ensure the URL is correctly configured in the trusted origins list.',
|
|
247
|
+
{
|
|
248
|
+
code: BASE_ERROR_CODES.FORBIDDEN,
|
|
249
|
+
status: 403,
|
|
250
|
+
data: {
|
|
251
|
+
url,
|
|
252
|
+
label,
|
|
253
|
+
trustedOrigins,
|
|
254
|
+
},
|
|
255
|
+
}
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
callbackURL && validateURL(callbackURL, 'callbackURL');
|
|
260
|
+
});
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { BASE_ERROR_CODES, C15TError } from '~/error';
|
|
2
|
+
import type { C15TContext, C15TPlugin } from '~/types';
|
|
3
|
+
import { createAuthMiddleware } from '../call';
|
|
4
|
+
|
|
5
|
+
import type { Adapter } from '~/db/adapters/types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Redacts sensitive information from context for error reporting
|
|
9
|
+
*
|
|
10
|
+
* @param context - The context object to redact
|
|
11
|
+
* @returns A sanitized version of the context
|
|
12
|
+
*/
|
|
13
|
+
function redactContext(context: unknown): Record<string, unknown> {
|
|
14
|
+
if (!context || typeof context !== 'object') {
|
|
15
|
+
return { type: typeof context };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const typedContext = context as C15TContext;
|
|
19
|
+
return {
|
|
20
|
+
baseURL: typedContext.baseURL,
|
|
21
|
+
storageType: typedContext.storage?.constructor.name,
|
|
22
|
+
pluginsCount: Array.isArray(typedContext.plugins)
|
|
23
|
+
? typedContext.plugins.length
|
|
24
|
+
: 0,
|
|
25
|
+
hasOptions: !!typedContext.options,
|
|
26
|
+
hasLogger: !!typedContext.logger,
|
|
27
|
+
hasPlugins: !!typedContext.plugins,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validates plugin initialization status
|
|
33
|
+
*
|
|
34
|
+
* @param plugins - Array of configured plugins
|
|
35
|
+
* @param initializedPlugins - Array of successfully initialized plugins
|
|
36
|
+
* @returns Array of failed plugin names, or null if all plugins initialized
|
|
37
|
+
*/
|
|
38
|
+
function validatePlugins(
|
|
39
|
+
plugins: C15TPlugin[] | undefined,
|
|
40
|
+
initializedPlugins: C15TPlugin[] | undefined
|
|
41
|
+
): string[] | null {
|
|
42
|
+
if (!plugins?.length) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const initializedNames = new Set(initializedPlugins?.map((p) => p.id) ?? []);
|
|
47
|
+
|
|
48
|
+
const failedPlugins = plugins
|
|
49
|
+
.filter((p) => !initializedNames.has(p.id))
|
|
50
|
+
.map((p) => p.id);
|
|
51
|
+
|
|
52
|
+
return failedPlugins.length > 0 ? failedPlugins : null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Middleware that validates the context for all routes
|
|
57
|
+
*
|
|
58
|
+
* This middleware ensures that the context object is properly structured and
|
|
59
|
+
* contains all required properties and services before allowing the request to proceed.
|
|
60
|
+
*
|
|
61
|
+
* @remarks
|
|
62
|
+
* The middleware performs comprehensive validation of:
|
|
63
|
+
* - Basic context structure
|
|
64
|
+
* - Required configuration options
|
|
65
|
+
* - Storage adapter availability
|
|
66
|
+
* - Logger availability
|
|
67
|
+
* - Plugin initialization status
|
|
68
|
+
* - Required services and dependencies
|
|
69
|
+
*
|
|
70
|
+
* @throws {C15TError} Throws appropriate errors for:
|
|
71
|
+
* - INVALID_CONFIGURATION: When context or options are invalid
|
|
72
|
+
* - STORAGE_ERROR: When storage adapter is not available
|
|
73
|
+
* - INITIALIZATION_FAILED: When required services failed to initialize
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // Using with memory adapter
|
|
78
|
+
* const router = createRouter(endpoints, {
|
|
79
|
+
* routerMiddleware: [
|
|
80
|
+
* {
|
|
81
|
+
* path: '/**',
|
|
82
|
+
* middleware: validateContextMiddleware
|
|
83
|
+
* }
|
|
84
|
+
* ]
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export const validateContextMiddleware = createAuthMiddleware(async (ctx) => {
|
|
89
|
+
const { context } = ctx;
|
|
90
|
+
|
|
91
|
+
// Basic context validation
|
|
92
|
+
if (!context || typeof context !== 'object') {
|
|
93
|
+
throw new C15TError(
|
|
94
|
+
'The context configuration is incomplete. Please ensure all required configuration options are provided and properly formatted.',
|
|
95
|
+
{
|
|
96
|
+
code: BASE_ERROR_CODES.INVALID_CONFIGURATION,
|
|
97
|
+
status: 500,
|
|
98
|
+
data: redactContext(context),
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Ensure the context is properly typed
|
|
104
|
+
const typedContext = context as C15TContext;
|
|
105
|
+
|
|
106
|
+
// Validate required configuration
|
|
107
|
+
if (!typedContext.options) {
|
|
108
|
+
throw new C15TError(
|
|
109
|
+
'The context configuration is missing required options. Please ensure the options object is properly configured.',
|
|
110
|
+
{
|
|
111
|
+
code: BASE_ERROR_CODES.INVALID_CONFIGURATION,
|
|
112
|
+
status: 500,
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Optional storage adapter validation
|
|
118
|
+
if (typedContext.storage) {
|
|
119
|
+
const storage = typedContext.storage as Adapter;
|
|
120
|
+
const requiredMethods = ['subjects', 'records', 'policies'];
|
|
121
|
+
const missingMethods = requiredMethods.filter(
|
|
122
|
+
(method) => !(method in storage)
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (missingMethods.length > 0) {
|
|
126
|
+
typedContext.logger?.warn?.('Storage adapter missing methods', {
|
|
127
|
+
missingMethods,
|
|
128
|
+
storageType: storage.constructor.name,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate logger (make it optional for memory adapter in development)
|
|
134
|
+
if (!typedContext.logger && process.env.NODE_ENV === 'production') {
|
|
135
|
+
throw new C15TError(
|
|
136
|
+
'Logger is required in production environment. Please configure a logger for your application.',
|
|
137
|
+
{
|
|
138
|
+
code: BASE_ERROR_CODES.INVALID_CONFIGURATION,
|
|
139
|
+
status: 500,
|
|
140
|
+
data: {
|
|
141
|
+
environment: process.env.NODE_ENV,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Validate plugins if any are configured
|
|
148
|
+
const failedPlugins = validatePlugins(
|
|
149
|
+
typedContext.options.plugins,
|
|
150
|
+
typedContext.plugins as C15TPlugin[] | undefined
|
|
151
|
+
);
|
|
152
|
+
if (failedPlugins) {
|
|
153
|
+
throw new C15TError(
|
|
154
|
+
'Plugin initialization failed. Some plugins could not be initialized properly. Please check your plugin configuration.',
|
|
155
|
+
{
|
|
156
|
+
code: BASE_ERROR_CODES.PLUGIN_INITIALIZATION_FAILED,
|
|
157
|
+
status: 500,
|
|
158
|
+
data: {
|
|
159
|
+
failedPlugins,
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Log successful validation if logger exists
|
|
166
|
+
typedContext.logger?.debug?.('Context validation successful', {
|
|
167
|
+
baseURL: typedContext.baseURL,
|
|
168
|
+
storageType: typedContext.storage?.constructor.name,
|
|
169
|
+
pluginsCount: Array.isArray(typedContext.plugins)
|
|
170
|
+
? typedContext.plugins.length
|
|
171
|
+
: 0,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return { context: typedContext };
|
|
175
|
+
});
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { c15tInstance } from '~/core';
|
|
3
|
+
import { memoryAdapter } from '~/db/adapters/memory-adapter';
|
|
4
|
+
import type { ConsentPolicy } from '~/db/schema';
|
|
5
|
+
import { BASE_ERROR_CODES } from '~/error';
|
|
6
|
+
import type { C15TContext } from '~/types';
|
|
7
|
+
import { setConsent } from '../set-consent';
|
|
8
|
+
|
|
9
|
+
describe('Consent Endpoints', () => {
|
|
10
|
+
let context: C15TContext;
|
|
11
|
+
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
const instance = await c15tInstance({
|
|
14
|
+
baseURL: 'http://localhost:3000',
|
|
15
|
+
database: memoryAdapter({}),
|
|
16
|
+
trustedOrigins: ['http://localhost:3000'],
|
|
17
|
+
secret: 'test-secret',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const contextResult = await instance.$context;
|
|
21
|
+
if (!contextResult.isOk()) {
|
|
22
|
+
throw new Error('Failed to initialize context');
|
|
23
|
+
}
|
|
24
|
+
context = contextResult.value;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('setConsent', () => {
|
|
28
|
+
// Helper function for common consent data
|
|
29
|
+
const createConsentData = (
|
|
30
|
+
type: 'cookie_banner' | 'privacy_policy',
|
|
31
|
+
overrides = {}
|
|
32
|
+
) => ({
|
|
33
|
+
type,
|
|
34
|
+
domain: 'example.com',
|
|
35
|
+
preferences: {
|
|
36
|
+
marketing: true,
|
|
37
|
+
analytics: true,
|
|
38
|
+
},
|
|
39
|
+
...overrides,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Helper function for common response checks
|
|
43
|
+
const expectValidConsentResponse = (
|
|
44
|
+
response: {
|
|
45
|
+
id: string;
|
|
46
|
+
givenAt: string;
|
|
47
|
+
subjectId: string;
|
|
48
|
+
domainId: string;
|
|
49
|
+
type: string;
|
|
50
|
+
status: string;
|
|
51
|
+
domain: string;
|
|
52
|
+
metadata?: unknown;
|
|
53
|
+
},
|
|
54
|
+
type: string,
|
|
55
|
+
extraChecks = {}
|
|
56
|
+
) => {
|
|
57
|
+
// biome-ignore lint/suspicious/noMisplacedAssertion: its okay
|
|
58
|
+
expect(response).toMatchObject({
|
|
59
|
+
type,
|
|
60
|
+
status: 'active',
|
|
61
|
+
domain: 'example.com',
|
|
62
|
+
metadata: undefined,
|
|
63
|
+
...extraChecks,
|
|
64
|
+
});
|
|
65
|
+
// biome-ignore lint/suspicious/noMisplacedAssertion: its okay
|
|
66
|
+
expect(typeof response.id).toBe('string');
|
|
67
|
+
// biome-ignore lint/suspicious/noMisplacedAssertion: its okay
|
|
68
|
+
expect(response.givenAt).toBeDefined();
|
|
69
|
+
// biome-ignore lint/suspicious/noMisplacedAssertion: its okay
|
|
70
|
+
expect(response.subjectId).toBeDefined();
|
|
71
|
+
// biome-ignore lint/suspicious/noMisplacedAssertion: its okay
|
|
72
|
+
expect(response.domainId).toBeDefined();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
it('should set cookie banner consent successfully', async () => {
|
|
76
|
+
const response = await setConsent({
|
|
77
|
+
context,
|
|
78
|
+
params: undefined,
|
|
79
|
+
query: undefined,
|
|
80
|
+
body: createConsentData('cookie_banner'),
|
|
81
|
+
});
|
|
82
|
+
expectValidConsentResponse(response, 'cookie_banner');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should set privacy policy consent successfully with external subject', async () => {
|
|
86
|
+
await context.registry.createSubject({
|
|
87
|
+
externalId: 'test-subject',
|
|
88
|
+
isIdentified: true,
|
|
89
|
+
identityProvider: 'test',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const response = await setConsent({
|
|
93
|
+
context,
|
|
94
|
+
params: undefined,
|
|
95
|
+
query: undefined,
|
|
96
|
+
body: createConsentData('privacy_policy', {
|
|
97
|
+
externalSubjectId: 'test-subject',
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
expectValidConsentResponse(response, 'privacy_policy', {
|
|
102
|
+
externalSubjectId: 'test-subject',
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe('Policy ID handling', () => {
|
|
107
|
+
let policy: ConsentPolicy;
|
|
108
|
+
|
|
109
|
+
beforeEach(async () => {
|
|
110
|
+
policy = await context.registry.createConsentPolicy({
|
|
111
|
+
name: 'Test Privacy Policy',
|
|
112
|
+
version: '1.0',
|
|
113
|
+
content: 'Test content',
|
|
114
|
+
contentHash: 'test-hash',
|
|
115
|
+
effectiveDate: new Date(),
|
|
116
|
+
updatedAt: new Date(),
|
|
117
|
+
isActive: true,
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should set consent with explicit policy ID', async () => {
|
|
122
|
+
const response = await setConsent({
|
|
123
|
+
context,
|
|
124
|
+
params: undefined,
|
|
125
|
+
query: undefined,
|
|
126
|
+
body: createConsentData('privacy_policy', { policyId: policy.id }),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
expectValidConsentResponse(response, 'privacy_policy');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should find latest policy when policy ID is not provided', async () => {
|
|
133
|
+
const response = await setConsent({
|
|
134
|
+
context,
|
|
135
|
+
params: undefined,
|
|
136
|
+
query: undefined,
|
|
137
|
+
body: createConsentData('privacy_policy'),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
expectValidConsentResponse(response, 'privacy_policy');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should error with invalid policy ID', async () => {
|
|
144
|
+
await expect(
|
|
145
|
+
setConsent({
|
|
146
|
+
context,
|
|
147
|
+
params: undefined,
|
|
148
|
+
query: undefined,
|
|
149
|
+
body: createConsentData('privacy_policy', {
|
|
150
|
+
policyId: 'invalid-id',
|
|
151
|
+
}),
|
|
152
|
+
})
|
|
153
|
+
).rejects.toMatchObject({
|
|
154
|
+
name: 'C15TError',
|
|
155
|
+
code: BASE_ERROR_CODES.NOT_FOUND,
|
|
156
|
+
status: 404,
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('Subject mapping validation', () => {
|
|
162
|
+
it('should validate that subjectId and externalSubjectId map to the same subject', async () => {
|
|
163
|
+
// Create a subject with external ID
|
|
164
|
+
const subject = await context.registry.createSubject({
|
|
165
|
+
externalId: 'test-subject',
|
|
166
|
+
isIdentified: true,
|
|
167
|
+
identityProvider: 'test',
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!subject) {
|
|
171
|
+
throw new Error('Failed to create test subject');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Test with matching IDs
|
|
175
|
+
const response = await setConsent({
|
|
176
|
+
context,
|
|
177
|
+
params: undefined,
|
|
178
|
+
query: undefined,
|
|
179
|
+
body: createConsentData('privacy_policy', {
|
|
180
|
+
subjectId: subject.id,
|
|
181
|
+
externalSubjectId: 'test-subject',
|
|
182
|
+
}),
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expectValidConsentResponse(response, 'privacy_policy', {
|
|
186
|
+
subjectId: subject.id,
|
|
187
|
+
externalSubjectId: 'test-subject',
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Create another subject with different external ID
|
|
191
|
+
const otherSubject = await context.registry.createSubject({
|
|
192
|
+
externalId: 'other-subject',
|
|
193
|
+
isIdentified: true,
|
|
194
|
+
identityProvider: 'test',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (!otherSubject) {
|
|
198
|
+
throw new Error('Failed to create other test subject');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Test with mismatched IDs
|
|
202
|
+
await expect(
|
|
203
|
+
setConsent({
|
|
204
|
+
context,
|
|
205
|
+
params: undefined,
|
|
206
|
+
query: undefined,
|
|
207
|
+
body: createConsentData('privacy_policy', {
|
|
208
|
+
subjectId: subject.id,
|
|
209
|
+
externalSubjectId: 'other-subject',
|
|
210
|
+
}),
|
|
211
|
+
})
|
|
212
|
+
).rejects.toMatchObject({
|
|
213
|
+
name: 'C15TError',
|
|
214
|
+
code: BASE_ERROR_CODES.BAD_REQUEST,
|
|
215
|
+
status: 400,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe('Error cases', () => {
|
|
221
|
+
it('should create anonymous subject when external subject is not found', async () => {
|
|
222
|
+
const response = await setConsent({
|
|
223
|
+
context,
|
|
224
|
+
params: undefined,
|
|
225
|
+
query: undefined,
|
|
226
|
+
body: createConsentData('privacy_policy', {
|
|
227
|
+
externalSubjectId: 'non-existent',
|
|
228
|
+
}),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
expectValidConsentResponse(response, 'privacy_policy', {
|
|
232
|
+
externalSubjectId: 'non-existent',
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('should error if subject ID is not found', async () => {
|
|
237
|
+
await expect(
|
|
238
|
+
setConsent({
|
|
239
|
+
context,
|
|
240
|
+
params: undefined,
|
|
241
|
+
query: undefined,
|
|
242
|
+
body: createConsentData('privacy_policy', {
|
|
243
|
+
subjectId: 'non-existent',
|
|
244
|
+
}),
|
|
245
|
+
})
|
|
246
|
+
).rejects.toMatchObject({
|
|
247
|
+
name: 'C15TError',
|
|
248
|
+
code: BASE_ERROR_CODES.NOT_FOUND,
|
|
249
|
+
status: 404,
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should handle invalid consent data', async () => {
|
|
254
|
+
await expect(
|
|
255
|
+
setConsent({
|
|
256
|
+
context,
|
|
257
|
+
params: undefined,
|
|
258
|
+
query: undefined,
|
|
259
|
+
body: createConsentData('cookie_banner', {
|
|
260
|
+
preferences: {
|
|
261
|
+
marketing: 'invalid' as unknown as boolean,
|
|
262
|
+
analytics: 'invalid' as unknown as boolean,
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
})
|
|
266
|
+
).rejects.toThrow('Invalid body parameters');
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
});
|