@c15t/backend 2.0.0-rc.1 → 2.0.0-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/README.md +3 -3
- package/dist/302.js +473 -0
- package/dist/583.js +540 -0
- package/dist/915.js +1771 -0
- package/dist/cache.cjs +5 -5
- package/dist/cache.js +4 -415
- package/dist/core.cjs +1356 -120
- package/dist/core.js +163 -1981
- package/dist/db/adapters/drizzle.cjs +1 -1
- package/dist/db/adapters/drizzle.js +1 -2
- package/dist/db/adapters/kysely.cjs +1 -1
- package/dist/db/adapters/kysely.js +1 -2
- package/dist/db/adapters/mongo.cjs +1 -1
- package/dist/db/adapters/mongo.js +1 -2
- package/dist/db/adapters/prisma.cjs +1 -1
- package/dist/db/adapters/prisma.js +1 -2
- package/dist/db/adapters/typeorm.cjs +1 -1
- package/dist/db/adapters/typeorm.js +1 -2
- package/dist/db/adapters.cjs +1 -1
- package/dist/db/migrator.cjs +1 -1
- package/dist/db/schema.cjs +43 -3
- package/dist/db/schema.js +35 -4
- package/dist/define-config.cjs +1 -1
- package/dist/edge.cjs +1106 -0
- package/dist/edge.js +190 -0
- package/dist/router.cjs +885 -123
- package/dist/router.js +1 -1507
- package/dist/{types.cjs → types/index.cjs} +1 -1
- package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
- package/{dist → dist-types}/cache/gvl-resolver.d.ts +0 -1
- package/{dist → dist-types}/cache/index.d.ts +0 -1
- package/{dist → dist-types}/cache/keys.d.ts +0 -1
- package/{dist → dist-types}/cache/types.d.ts +0 -1
- package/{dist → dist-types}/core.d.ts +8 -1
- package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
- package/dist-types/db/registry/consent-policy.d.ts +78 -0
- package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
- package/dist-types/db/registry/index.d.ts +118 -0
- package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
- package/{dist → dist-types}/db/registry/subject.d.ts +0 -2
- package/{dist → dist-types}/db/registry/types.d.ts +1 -1
- package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
- package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
- package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -32
- package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -2
- package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +3 -3
- package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +7 -2
- package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +455 -28
- package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
- package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -3
- package/{dist → dist-types}/db/schema/index.d.ts +908 -86
- package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
- package/dist-types/define-config.d.ts +17 -0
- package/dist-types/edge/index.d.ts +5 -0
- package/dist-types/edge/init-handler.d.ts +40 -0
- package/dist-types/edge/resolve-consent.d.ts +80 -0
- package/dist-types/edge/types.d.ts +13 -0
- package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
- package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
- package/{dist → dist-types}/handlers/init/index.d.ts +2 -3
- package/dist-types/handlers/init/policy.d.ts +26 -0
- package/dist-types/handlers/init/resolve-init.d.ts +44 -0
- package/dist-types/handlers/init/translations.d.ts +48 -0
- package/dist-types/handlers/legal-document/current.handler.d.ts +11 -0
- package/dist-types/handlers/legal-document/snapshot.d.ts +39 -0
- package/dist-types/handlers/policy/snapshot.d.ts +99 -0
- package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
- package/{dist → dist-types}/handlers/subject/get.handler.d.ts +3 -2
- package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/subject/list.handler.d.ts +3 -2
- package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -2
- package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
- package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +3 -1
- package/{dist → dist-types}/init.d.ts +4 -7
- package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
- package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
- package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
- package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +0 -1
- package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
- package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
- package/dist-types/policies/builder.d.ts +127 -0
- package/dist-types/policies/defaults.d.ts +2 -0
- package/dist-types/policies/matchers.d.ts +3 -0
- package/{dist → dist-types}/router.d.ts +0 -1
- package/{dist → dist-types}/routes/consent.d.ts +0 -1
- package/{dist → dist-types}/routes/index.d.ts +1 -1
- package/{dist → dist-types}/routes/init.d.ts +0 -1
- package/dist-types/routes/legal-document.d.ts +7 -0
- package/{dist → dist-types}/routes/status.d.ts +0 -1
- package/{dist → dist-types}/routes/subject.d.ts +0 -1
- package/{dist → dist-types}/types/api.d.ts +0 -1
- package/dist-types/types/index.d.ts +464 -0
- package/dist-types/utils/background.d.ts +6 -0
- package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
- package/{dist → dist-types}/utils/env.d.ts +0 -1
- package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
- package/{dist → dist-types}/utils/instrumentation.d.ts +2 -3
- package/{dist → dist-types}/utils/logger.d.ts +0 -1
- package/{dist → dist-types}/utils/metrics.d.ts +0 -1
- package/dist-types/version.d.ts +1 -0
- package/docs/README.md +49 -0
- package/docs/api/configuration.md +208 -0
- package/docs/api/endpoints.md +211 -0
- package/docs/guides/caching.md +85 -0
- package/docs/guides/database-setup.md +128 -0
- package/docs/guides/edge-deployment.md +251 -0
- package/docs/guides/framework-integration.md +142 -0
- package/docs/guides/iab-tcf.md +89 -0
- package/docs/guides/observability.md +96 -0
- package/docs/guides/policy-packs.md +396 -0
- package/docs/quickstart.md +129 -0
- package/package.json +51 -37
- package/.turbo/turbo-build.log +0 -49
- package/CHANGELOG.md +0 -99
- package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
- package/dist/cache/adapters/index.d.ts.map +0 -1
- package/dist/cache/adapters/memory.d.ts.map +0 -1
- package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
- package/dist/cache/gvl-resolver.d.ts.map +0 -1
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/keys.d.ts.map +0 -1
- package/dist/cache/types.d.ts.map +0 -1
- package/dist/core.d.ts.map +0 -1
- package/dist/db/adapters/drizzle.d.ts +0 -2
- package/dist/db/adapters/drizzle.d.ts.map +0 -1
- package/dist/db/adapters/index.d.ts +0 -2
- package/dist/db/adapters/index.d.ts.map +0 -1
- package/dist/db/adapters/kysely.d.ts +0 -2
- package/dist/db/adapters/kysely.d.ts.map +0 -1
- package/dist/db/adapters/mongo.d.ts +0 -2
- package/dist/db/adapters/mongo.d.ts.map +0 -1
- package/dist/db/adapters/prisma.d.ts +0 -2
- package/dist/db/adapters/prisma.d.ts.map +0 -1
- package/dist/db/adapters/typeorm.d.ts +0 -2
- package/dist/db/adapters/typeorm.d.ts.map +0 -1
- package/dist/db/migrator/index.d.ts.map +0 -1
- package/dist/db/registry/consent-policy.d.ts +0 -23
- package/dist/db/registry/consent-policy.d.ts.map +0 -1
- package/dist/db/registry/consent-purpose.d.ts.map +0 -1
- package/dist/db/registry/domain.d.ts.map +0 -1
- package/dist/db/registry/index.d.ts +0 -57
- package/dist/db/registry/index.d.ts.map +0 -1
- package/dist/db/registry/subject.d.ts.map +0 -1
- package/dist/db/registry/types.d.ts.map +0 -1
- package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
- package/dist/db/registry/utils.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/index.d.ts.map +0 -1
- package/dist/db/tenant-scope.d.ts.map +0 -1
- package/dist/define-config.d.ts +0 -5
- package/dist/define-config.d.ts.map +0 -1
- package/dist/handlers/consent/check.handler.d.ts.map +0 -1
- package/dist/handlers/consent/index.d.ts +0 -12
- package/dist/handlers/consent/index.d.ts.map +0 -1
- package/dist/handlers/init/geo.d.ts.map +0 -1
- package/dist/handlers/init/index.d.ts.map +0 -1
- package/dist/handlers/init/translations.d.ts +0 -28
- package/dist/handlers/init/translations.d.ts.map +0 -1
- package/dist/handlers/status/index.d.ts +0 -7
- package/dist/handlers/status/index.d.ts.map +0 -1
- package/dist/handlers/status/status.handler.d.ts.map +0 -1
- package/dist/handlers/subject/get.handler.d.ts.map +0 -1
- package/dist/handlers/subject/index.d.ts +0 -10
- package/dist/handlers/subject/index.d.ts.map +0 -1
- package/dist/handlers/subject/list.handler.d.ts.map +0 -1
- package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
- package/dist/handlers/subject/post.handler.d.ts.map +0 -1
- package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
- package/dist/init.d.ts.map +0 -1
- package/dist/middleware/auth/index.d.ts.map +0 -1
- package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
- package/dist/middleware/cors/cors.d.ts.map +0 -1
- package/dist/middleware/cors/index.d.ts +0 -30
- package/dist/middleware/cors/index.d.ts.map +0 -1
- package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
- package/dist/middleware/cors/process-cors.d.ts.map +0 -1
- package/dist/middleware/openapi/config.d.ts.map +0 -1
- package/dist/middleware/openapi/handlers.d.ts.map +0 -1
- package/dist/middleware/openapi/index.d.ts +0 -12
- package/dist/middleware/openapi/index.d.ts.map +0 -1
- package/dist/middleware/process-ip/index.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/routes/consent.d.ts.map +0 -1
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/init.d.ts.map +0 -1
- package/dist/routes/status.d.ts.map +0 -1
- package/dist/routes/subject.d.ts.map +0 -1
- package/dist/types/api.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -255
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/create-telemetry-options.d.ts.map +0 -1
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/extract-error-message.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/instrumentation.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/metrics.d.ts.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/knip.json +0 -31
- package/rslib.config.ts +0 -93
- package/src/cache/adapters/cloudflare-kv.ts +0 -71
- package/src/cache/adapters/index.ts +0 -22
- package/src/cache/adapters/memory.ts +0 -111
- package/src/cache/adapters/upstash-redis.ts +0 -113
- package/src/cache/gvl-resolver.ts +0 -289
- package/src/cache/index.ts +0 -34
- package/src/cache/keys.ts +0 -68
- package/src/cache/types.ts +0 -66
- package/src/core.ts +0 -368
- package/src/db/migrator/index.ts +0 -80
- package/src/db/registry/consent-policy.test.ts +0 -451
- package/src/db/registry/consent-policy.ts +0 -82
- package/src/db/registry/consent-purpose.test.ts +0 -428
- package/src/db/registry/consent-purpose.ts +0 -61
- package/src/db/registry/domain.test.ts +0 -445
- package/src/db/registry/domain.ts +0 -91
- package/src/db/registry/index.ts +0 -14
- package/src/db/registry/subject.test.ts +0 -388
- package/src/db/registry/subject.ts +0 -129
- package/src/db/registry/types.ts +0 -10
- package/src/db/registry/utils/generate-id.test.ts +0 -216
- package/src/db/registry/utils/generate-id.ts +0 -133
- package/src/db/registry/utils.ts +0 -133
- package/src/db/schema/1.0.0/audit-log.ts +0 -15
- package/src/db/schema/1.0.0/consent-policy.ts +0 -14
- package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
- package/src/db/schema/1.0.0/consent-record.ts +0 -10
- package/src/db/schema/1.0.0/consent.ts +0 -20
- package/src/db/schema/1.0.0/domain.ts +0 -12
- package/src/db/schema/1.0.0/index.ts +0 -48
- package/src/db/schema/1.0.0/subject.ts +0 -12
- package/src/db/schema/2.0.0/audit-log.ts +0 -18
- package/src/db/schema/2.0.0/consent-policy.ts +0 -28
- package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
- package/src/db/schema/2.0.0/consent.ts +0 -26
- package/src/db/schema/2.0.0/domain.ts +0 -12
- package/src/db/schema/2.0.0/index.ts +0 -47
- package/src/db/schema/2.0.0/subject.ts +0 -14
- package/src/db/schema/index.ts +0 -15
- package/src/db/tenant-scope.test.ts +0 -750
- package/src/db/tenant-scope.ts +0 -103
- package/src/define-config.ts +0 -5
- package/src/handlers/consent/check.handler.ts +0 -126
- package/src/handlers/init/geo.test.ts +0 -317
- package/src/handlers/init/geo.ts +0 -195
- package/src/handlers/init/index.test.ts +0 -205
- package/src/handlers/init/index.ts +0 -114
- package/src/handlers/init/translations.test.ts +0 -121
- package/src/handlers/init/translations.ts +0 -72
- package/src/handlers/status/status.handler.test.ts +0 -155
- package/src/handlers/status/status.handler.ts +0 -51
- package/src/handlers/subject/get.handler.ts +0 -93
- package/src/handlers/subject/list.handler.ts +0 -93
- package/src/handlers/subject/patch.handler.ts +0 -122
- package/src/handlers/subject/post.handler.test.ts +0 -294
- package/src/handlers/subject/post.handler.ts +0 -254
- package/src/handlers/utils/consent-enrichment.test.ts +0 -380
- package/src/handlers/utils/consent-enrichment.ts +0 -218
- package/src/init.test.ts +0 -126
- package/src/init.ts +0 -87
- package/src/middleware/auth/index.ts +0 -11
- package/src/middleware/auth/validate-api-key.test.ts +0 -86
- package/src/middleware/auth/validate-api-key.ts +0 -107
- package/src/middleware/cors/cors.test.ts +0 -135
- package/src/middleware/cors/cors.ts +0 -186
- package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
- package/src/middleware/cors/is-origin-trusted.ts +0 -130
- package/src/middleware/cors/process-cors.ts +0 -91
- package/src/middleware/openapi/config.ts +0 -29
- package/src/middleware/openapi/handlers.ts +0 -34
- package/src/middleware/process-ip/index.test.ts +0 -195
- package/src/middleware/process-ip/index.ts +0 -199
- package/src/router.ts +0 -15
- package/src/routes/consent.ts +0 -52
- package/src/routes/index.ts +0 -10
- package/src/routes/init.ts +0 -102
- package/src/routes/status.ts +0 -46
- package/src/routes/subject.ts +0 -152
- package/src/types/api.ts +0 -48
- package/src/types/index.ts +0 -288
- package/src/utils/create-telemetry-options.test.ts +0 -302
- package/src/utils/create-telemetry-options.ts +0 -229
- package/src/utils/env.ts +0 -84
- package/src/utils/extract-error-message.ts +0 -21
- package/src/utils/instrumentation.test.ts +0 -185
- package/src/utils/instrumentation.ts +0 -196
- package/src/utils/logger.ts +0 -41
- package/src/utils/metrics.test.ts +0 -323
- package/src/utils/metrics.ts +0 -402
- package/src/utils/telemetry-pii.test.ts +0 -325
- package/src/version.ts +0 -2
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -28
- /package/dist/{types.js → types/index.js} +0 -0
- /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
- /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
- /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
- /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
- /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
- /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
- /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
package/src/db/tenant-scope.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import type { InferFumaDB } from 'fumadb';
|
|
2
|
-
import type { LatestDB } from './schema';
|
|
3
|
-
|
|
4
|
-
type ORM = ReturnType<InferFumaDB<typeof LatestDB>['orm']>;
|
|
5
|
-
|
|
6
|
-
const SCOPED_METHODS = new Set([
|
|
7
|
-
'create',
|
|
8
|
-
'createMany',
|
|
9
|
-
'findFirst',
|
|
10
|
-
'findMany',
|
|
11
|
-
'count',
|
|
12
|
-
'updateMany',
|
|
13
|
-
'deleteMany',
|
|
14
|
-
'upsert',
|
|
15
|
-
'transaction',
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Wraps a FumaDB ORM instance to automatically scope all queries to a specific tenant.
|
|
20
|
-
*
|
|
21
|
-
* Uses a Proxy so that any ORM method not explicitly handled will throw,
|
|
22
|
-
* preventing future methods from silently bypassing tenant scoping.
|
|
23
|
-
*
|
|
24
|
-
* - `create`/`createMany`: Injects `tenantId` into the data
|
|
25
|
-
* - `findFirst`/`findMany`/`count`: Adds `tenantId` filter to the `where` clause
|
|
26
|
-
* - `updateMany`/`deleteMany`: Adds `tenantId` filter to the `where` clause
|
|
27
|
-
* - `upsert`: Adds `tenantId` filter to the `where` clause and injects into create data
|
|
28
|
-
* - `transaction`: Returns a tenant-scoped transaction
|
|
29
|
-
*
|
|
30
|
-
* When `tenantId` is not set, this function should not be called — the raw ORM is used directly.
|
|
31
|
-
*/
|
|
32
|
-
export function withTenantScope(db: ORM, tenantId: string): ORM {
|
|
33
|
-
const scopeWhere = (originalWhere: ((b: any) => any) | undefined, b: any) => {
|
|
34
|
-
const tenantFilter = b('tenantId', '=', tenantId);
|
|
35
|
-
return originalWhere ? b.and(originalWhere(b), tenantFilter) : tenantFilter;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const scopedMethods: Record<string, (...args: any[]) => any> = {
|
|
39
|
-
create: (table: any, data: any) => db.create(table, { ...data, tenantId }),
|
|
40
|
-
|
|
41
|
-
createMany: (table: any, items: any[]) =>
|
|
42
|
-
db.createMany(
|
|
43
|
-
table,
|
|
44
|
-
items.map((d: any) => ({ ...d, tenantId }))
|
|
45
|
-
),
|
|
46
|
-
|
|
47
|
-
findFirst: (table: any, opts: any) =>
|
|
48
|
-
db.findFirst(table, {
|
|
49
|
-
...opts,
|
|
50
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
51
|
-
}),
|
|
52
|
-
|
|
53
|
-
findMany: (table: any, opts?: any) =>
|
|
54
|
-
db.findMany(table, {
|
|
55
|
-
...opts,
|
|
56
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
57
|
-
}),
|
|
58
|
-
|
|
59
|
-
count: (table: any, opts?: any) =>
|
|
60
|
-
db.count(table, {
|
|
61
|
-
...opts,
|
|
62
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
63
|
-
}),
|
|
64
|
-
|
|
65
|
-
updateMany: (table: any, opts: any) =>
|
|
66
|
-
db.updateMany(table, {
|
|
67
|
-
...opts,
|
|
68
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
69
|
-
}),
|
|
70
|
-
|
|
71
|
-
deleteMany: (table: any, opts: any) =>
|
|
72
|
-
db.deleteMany(table, {
|
|
73
|
-
...opts,
|
|
74
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
75
|
-
}),
|
|
76
|
-
|
|
77
|
-
upsert: (table: any, opts: any) =>
|
|
78
|
-
db.upsert(table, {
|
|
79
|
-
...opts,
|
|
80
|
-
where: (b: any) => scopeWhere(opts?.where, b),
|
|
81
|
-
create: { ...opts.create, tenantId },
|
|
82
|
-
}),
|
|
83
|
-
|
|
84
|
-
transaction: (fn: any) =>
|
|
85
|
-
db.transaction((tx: any) => fn(withTenantScope(tx, tenantId))),
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
return new Proxy(db, {
|
|
89
|
-
get(_target, prop, _receiver) {
|
|
90
|
-
if (typeof prop === 'string' && SCOPED_METHODS.has(prop)) {
|
|
91
|
-
return scopedMethods[prop];
|
|
92
|
-
}
|
|
93
|
-
// Allow symbol access (e.g. Symbol.toStringTag) and standard object props
|
|
94
|
-
if (typeof prop === 'symbol') {
|
|
95
|
-
return Reflect.get(db, prop);
|
|
96
|
-
}
|
|
97
|
-
throw new Error(
|
|
98
|
-
`withTenantScope: method "${prop}" is not tenant-scoped. ` +
|
|
99
|
-
'Add an explicit scoped wrapper before using it.'
|
|
100
|
-
);
|
|
101
|
-
},
|
|
102
|
-
}) as ORM;
|
|
103
|
-
}
|
package/src/define-config.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GET /consents/check handler - Pre-banner cross-device consent check.
|
|
3
|
-
*
|
|
4
|
-
* @packageDocumentation
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { Context } from 'hono';
|
|
8
|
-
import { HTTPException } from 'hono/http-exception';
|
|
9
|
-
import type { C15TContext } from '~/types';
|
|
10
|
-
import { extractErrorMessage } from '~/utils/extract-error-message';
|
|
11
|
-
import { getMetrics } from '~/utils/metrics';
|
|
12
|
-
import { resolveConsentPolicies } from '../utils/consent-enrichment';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Handles checking if an externalId has consented to specific policies.
|
|
16
|
-
*
|
|
17
|
-
* Use this endpoint BEFORE showing consent banners to check if the user
|
|
18
|
-
* has already consented on another device.
|
|
19
|
-
*
|
|
20
|
-
* Returns minimal data (just booleans) for privacy - no subject IDs,
|
|
21
|
-
* no consent details, no PII.
|
|
22
|
-
*/
|
|
23
|
-
export const checkConsentHandler = async (c: Context) => {
|
|
24
|
-
const ctx = c.get('c15tContext') as C15TContext;
|
|
25
|
-
const logger = ctx.logger;
|
|
26
|
-
logger.info('Handling GET /consents/check request');
|
|
27
|
-
|
|
28
|
-
const { db, registry } = ctx;
|
|
29
|
-
|
|
30
|
-
const externalId = c.req.query('externalId');
|
|
31
|
-
const type = c.req.query('type');
|
|
32
|
-
|
|
33
|
-
if (!externalId) {
|
|
34
|
-
throw new HTTPException(422, {
|
|
35
|
-
message: 'externalId query parameter is required',
|
|
36
|
-
cause: { code: 'EXTERNAL_ID_REQUIRED' },
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!type) {
|
|
41
|
-
throw new HTTPException(422, {
|
|
42
|
-
message: 'type query parameter is required',
|
|
43
|
-
cause: { code: 'TYPE_REQUIRED' },
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const types = type.split(',').map((t) => t.trim());
|
|
48
|
-
|
|
49
|
-
logger.debug('Request parameters', { externalId, types });
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// Find all subjects with this externalId
|
|
53
|
-
const subjects = await db.findMany('subject', {
|
|
54
|
-
where: (b) => b('externalId', '=', externalId),
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
const subjectIds = subjects.map((s) => s.id);
|
|
58
|
-
|
|
59
|
-
// Initialize results
|
|
60
|
-
const results: Record<
|
|
61
|
-
string,
|
|
62
|
-
{ hasConsent: boolean; isLatestPolicy: boolean }
|
|
63
|
-
> = {};
|
|
64
|
-
for (const t of types) {
|
|
65
|
-
results[t] = { hasConsent: false, isLatestPolicy: false };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// If no subjects found, return all false
|
|
69
|
-
if (subjectIds.length === 0) {
|
|
70
|
-
logger.debug('No subjects found for externalId', { externalId });
|
|
71
|
-
return c.json({ results });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Get all consents for these subjects
|
|
75
|
-
const allConsents = await Promise.all(
|
|
76
|
-
subjectIds.map((subjectId) =>
|
|
77
|
-
db.findMany('consent', {
|
|
78
|
-
where: (b) => b('subjectId', '=', subjectId),
|
|
79
|
-
})
|
|
80
|
-
)
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const consents = allConsents.flat();
|
|
84
|
-
|
|
85
|
-
const policyInfos = await resolveConsentPolicies(consents, {
|
|
86
|
-
db,
|
|
87
|
-
registry,
|
|
88
|
-
});
|
|
89
|
-
for (const info of policyInfos) {
|
|
90
|
-
if (!types.includes(info.policyType)) continue;
|
|
91
|
-
const entry = results[info.policyType];
|
|
92
|
-
if (entry) {
|
|
93
|
-
entry.hasConsent = true;
|
|
94
|
-
if (info.isLatestPolicy) {
|
|
95
|
-
entry.isLatestPolicy = true;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
logger.debug('Consent check results', { externalId, results });
|
|
101
|
-
|
|
102
|
-
// Record consent check metrics
|
|
103
|
-
const metrics = getMetrics();
|
|
104
|
-
if (metrics) {
|
|
105
|
-
for (const [type, result] of Object.entries(results)) {
|
|
106
|
-
metrics.recordConsentCheck(type, result.hasConsent);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return c.json({ results });
|
|
111
|
-
} catch (error) {
|
|
112
|
-
logger.error('Error in GET /consents/check handler', {
|
|
113
|
-
error: extractErrorMessage(error),
|
|
114
|
-
errorType: error instanceof Error ? error.constructor.name : typeof error,
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
if (error instanceof HTTPException) {
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
throw new HTTPException(500, {
|
|
122
|
-
message: 'Internal server error',
|
|
123
|
-
cause: { code: 'INTERNAL_SERVER_ERROR' },
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
};
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { checkJurisdiction } from './geo';
|
|
3
|
-
|
|
4
|
-
describe('checkJurisdiction', () => {
|
|
5
|
-
describe('GDPR jurisdiction (EU countries)', () => {
|
|
6
|
-
const euCountries = [
|
|
7
|
-
'AT',
|
|
8
|
-
'BE',
|
|
9
|
-
'BG',
|
|
10
|
-
'HR',
|
|
11
|
-
'CY',
|
|
12
|
-
'CZ',
|
|
13
|
-
'DK',
|
|
14
|
-
'EE',
|
|
15
|
-
'FI',
|
|
16
|
-
'FR',
|
|
17
|
-
'DE',
|
|
18
|
-
'GR',
|
|
19
|
-
'HU',
|
|
20
|
-
'IE',
|
|
21
|
-
'IT',
|
|
22
|
-
'LV',
|
|
23
|
-
'LT',
|
|
24
|
-
'LU',
|
|
25
|
-
'MT',
|
|
26
|
-
'NL',
|
|
27
|
-
'PL',
|
|
28
|
-
'PT',
|
|
29
|
-
'RO',
|
|
30
|
-
'SK',
|
|
31
|
-
'SI',
|
|
32
|
-
'ES',
|
|
33
|
-
'SE',
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
it.each(
|
|
37
|
-
euCountries
|
|
38
|
-
)('should identify %s as GDPR jurisdiction', (countryCode) => {
|
|
39
|
-
const jurisdiction = checkJurisdiction(countryCode);
|
|
40
|
-
|
|
41
|
-
expect(jurisdiction).toBe('GDPR');
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('GDPR jurisdiction (EEA countries)', () => {
|
|
46
|
-
const eeaCountries = ['IS', 'NO', 'LI'];
|
|
47
|
-
|
|
48
|
-
it.each(
|
|
49
|
-
eeaCountries
|
|
50
|
-
)('should identify %s as GDPR jurisdiction', (countryCode) => {
|
|
51
|
-
const jurisdiction = checkJurisdiction(countryCode);
|
|
52
|
-
|
|
53
|
-
expect(jurisdiction).toBe('GDPR');
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
describe('GDPR jurisdiction (UK)', () => {
|
|
58
|
-
it('should identify GB as GDPR jurisdiction', () => {
|
|
59
|
-
const jurisdiction = checkJurisdiction('GB');
|
|
60
|
-
|
|
61
|
-
expect(jurisdiction).toBe('UK_GDPR');
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
describe('Other specific jurisdictions', () => {
|
|
66
|
-
const jurisdictionCases = [
|
|
67
|
-
{ country: 'CH', code: 'CH' },
|
|
68
|
-
{ country: 'BR', code: 'BR' },
|
|
69
|
-
{ country: 'CA', code: 'PIPEDA' },
|
|
70
|
-
{ country: 'AU', code: 'AU' },
|
|
71
|
-
{ country: 'JP', code: 'APPI' },
|
|
72
|
-
{ country: 'KR', code: 'PIPA' },
|
|
73
|
-
] as const;
|
|
74
|
-
|
|
75
|
-
it.each(
|
|
76
|
-
jurisdictionCases
|
|
77
|
-
)('should identify $country as $code jurisdiction', ({ country, code }) => {
|
|
78
|
-
const jurisdiction = checkJurisdiction(country);
|
|
79
|
-
|
|
80
|
-
expect(jurisdiction).toBe(code);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('Non-regulated countries', () => {
|
|
85
|
-
const nonRegulatedCountries = [
|
|
86
|
-
'US', // United States (outside CCPA regions)
|
|
87
|
-
'RU', // Russia
|
|
88
|
-
'CN', // China
|
|
89
|
-
'IN', // India
|
|
90
|
-
'MX', // Mexico
|
|
91
|
-
'AR', // Argentina
|
|
92
|
-
'EG', // Egypt
|
|
93
|
-
'ZA', // South Africa
|
|
94
|
-
'TH', // Thailand
|
|
95
|
-
'PH', // Philippines
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
it.each(
|
|
99
|
-
nonRegulatedCountries
|
|
100
|
-
)('should identify %s as non-regulated (NONE jurisdiction)', (countryCode) => {
|
|
101
|
-
const jurisdiction = checkJurisdiction(countryCode);
|
|
102
|
-
|
|
103
|
-
expect(jurisdiction).toBe('NONE');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe('Edge cases', () => {
|
|
108
|
-
it('should handle null country code by defaulting to show banner with NONE jurisdiction', () => {
|
|
109
|
-
const jurisdiction = checkJurisdiction(null);
|
|
110
|
-
|
|
111
|
-
expect(jurisdiction).toBe('NONE');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should handle empty string country code by defaulting to show banner with NONE jurisdiction', () => {
|
|
115
|
-
const jurisdiction = checkJurisdiction('');
|
|
116
|
-
|
|
117
|
-
expect(jurisdiction).toBe('NONE');
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should handle lowercase country codes correctly', () => {
|
|
121
|
-
const jurisdiction = checkJurisdiction('de');
|
|
122
|
-
|
|
123
|
-
// Should now match because we normalize to uppercase
|
|
124
|
-
expect(jurisdiction).toBe('GDPR');
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should handle mixed case country codes across different jurisdictions', () => {
|
|
128
|
-
const testCases = [
|
|
129
|
-
{ input: 'de', expectedJurisdiction: 'GDPR' },
|
|
130
|
-
{ input: 'De', expectedJurisdiction: 'GDPR' },
|
|
131
|
-
{ input: 'DE', expectedJurisdiction: 'GDPR' },
|
|
132
|
-
{ input: 'ch', expectedJurisdiction: 'CH' },
|
|
133
|
-
{ input: 'Ch', expectedJurisdiction: 'CH' },
|
|
134
|
-
{ input: 'CH', expectedJurisdiction: 'CH' },
|
|
135
|
-
{ input: 'ca', expectedJurisdiction: 'PIPEDA' },
|
|
136
|
-
{ input: 'Ca', expectedJurisdiction: 'PIPEDA' },
|
|
137
|
-
{ input: 'CA', expectedJurisdiction: 'PIPEDA' },
|
|
138
|
-
] as const;
|
|
139
|
-
|
|
140
|
-
for (const { input, expectedJurisdiction } of testCases) {
|
|
141
|
-
const jurisdiction = checkJurisdiction(input);
|
|
142
|
-
|
|
143
|
-
expect(jurisdiction).toBe(expectedJurisdiction);
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should handle invalid country codes', () => {
|
|
148
|
-
const invalidCodes = ['XX', 'ZZ', '123', 'ABC'];
|
|
149
|
-
|
|
150
|
-
for (const code of invalidCodes) {
|
|
151
|
-
const jurisdiction = checkJurisdiction(code);
|
|
152
|
-
|
|
153
|
-
expect(jurisdiction).toBe('NONE');
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe('Return value structure', () => {
|
|
159
|
-
it('should always return an object with required properties', () => {
|
|
160
|
-
const jurisdiction = checkJurisdiction('DE');
|
|
161
|
-
|
|
162
|
-
expect(jurisdiction).toBe('GDPR');
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should return consistent types regardless of input', () => {
|
|
166
|
-
const inputs = ['DE', 'US', 'GB', 'XX', '', null];
|
|
167
|
-
|
|
168
|
-
for (const input of inputs) {
|
|
169
|
-
const jurisdiction = checkJurisdiction(input);
|
|
170
|
-
|
|
171
|
-
expect(typeof jurisdiction).toBe('string');
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('Comprehensive jurisdiction mapping', () => {
|
|
177
|
-
it('should correctly map all supported jurisdictions', () => {
|
|
178
|
-
// Test one representative from each jurisdiction group
|
|
179
|
-
const testCases = [
|
|
180
|
-
{
|
|
181
|
-
input: 'DE',
|
|
182
|
-
expectedJurisdiction: 'GDPR' as const,
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
input: 'NO',
|
|
186
|
-
expectedJurisdiction: 'GDPR' as const,
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
input: 'GB',
|
|
190
|
-
expectedJurisdiction: 'UK_GDPR' as const,
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
input: 'CH',
|
|
194
|
-
expectedJurisdiction: 'CH' as const,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
input: 'BR',
|
|
198
|
-
expectedJurisdiction: 'BR' as const,
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
input: 'CA',
|
|
202
|
-
expectedJurisdiction: 'PIPEDA' as const,
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
input: 'AU',
|
|
206
|
-
expectedJurisdiction: 'AU' as const,
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
input: 'JP',
|
|
210
|
-
expectedJurisdiction: 'APPI' as const,
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
input: 'KR',
|
|
214
|
-
expectedJurisdiction: 'PIPA' as const,
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
input: 'US',
|
|
218
|
-
expectedJurisdiction: 'NONE' as const,
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
input: null,
|
|
222
|
-
expectedJurisdiction: 'NONE' as const,
|
|
223
|
-
},
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
for (const { input, expectedJurisdiction } of testCases) {
|
|
227
|
-
const jurisdiction = checkJurisdiction(input);
|
|
228
|
-
|
|
229
|
-
expect(jurisdiction).toBe(expectedJurisdiction);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
describe('Quebec Law 25 jurisdiction (CA regions)', () => {
|
|
235
|
-
it('should identify CA-QC as QC_LAW25 jurisdiction (case-insensitive)', () => {
|
|
236
|
-
const cases = ['QC', 'qc', 'Qc'];
|
|
237
|
-
|
|
238
|
-
for (const region of cases) {
|
|
239
|
-
const jurisdiction = checkJurisdiction('CA', region);
|
|
240
|
-
|
|
241
|
-
expect(jurisdiction).toBe('QC_LAW25');
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('should handle dash-separated region codes for Quebec', () => {
|
|
246
|
-
const cases = ['CA-QC', 'ca-qc', 'Ca-Qc'];
|
|
247
|
-
|
|
248
|
-
for (const region of cases) {
|
|
249
|
-
const jurisdiction = checkJurisdiction('CA', region);
|
|
250
|
-
|
|
251
|
-
expect(jurisdiction).toBe('QC_LAW25');
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('should return PIPEDA for non-Quebec Canadian provinces', () => {
|
|
256
|
-
const nonQuebecRegions = ['ON', 'BC', 'AB', null];
|
|
257
|
-
|
|
258
|
-
for (const region of nonQuebecRegions) {
|
|
259
|
-
const jurisdiction = checkJurisdiction('CA', region as string | null);
|
|
260
|
-
|
|
261
|
-
expect(jurisdiction).toBe('PIPEDA');
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it('should return PIPEDA for dash-separated non-Quebec Canadian provinces', () => {
|
|
266
|
-
const nonQuebecRegions = ['CA-ON', 'CA-BC', 'CA-AB'];
|
|
267
|
-
|
|
268
|
-
for (const region of nonQuebecRegions) {
|
|
269
|
-
const jurisdiction = checkJurisdiction('CA', region);
|
|
270
|
-
|
|
271
|
-
expect(jurisdiction).toBe('PIPEDA');
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
describe('CCPA jurisdiction (US regions)', () => {
|
|
277
|
-
it('should identify US-CA as CCPA jurisdiction (case-insensitive)', () => {
|
|
278
|
-
const cases = ['CA', 'ca', 'Ca'];
|
|
279
|
-
|
|
280
|
-
for (const region of cases) {
|
|
281
|
-
const jurisdiction = checkJurisdiction('US', region);
|
|
282
|
-
|
|
283
|
-
expect(jurisdiction).toBe('CCPA');
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should handle dash-separated region codes for California', () => {
|
|
288
|
-
const cases = ['US-CA', 'us-ca', 'Us-Ca'];
|
|
289
|
-
|
|
290
|
-
for (const region of cases) {
|
|
291
|
-
const jurisdiction = checkJurisdiction('US', region);
|
|
292
|
-
|
|
293
|
-
expect(jurisdiction).toBe('CCPA');
|
|
294
|
-
}
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it('should not apply CCPA for non-CCPA US regions', () => {
|
|
298
|
-
const nonCcpaRegions = ['NY', 'TX', 'WA', 'FL', null];
|
|
299
|
-
|
|
300
|
-
for (const region of nonCcpaRegions) {
|
|
301
|
-
const jurisdiction = checkJurisdiction('US', region as string | null);
|
|
302
|
-
|
|
303
|
-
expect(jurisdiction).toBe('NONE');
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('should not apply CCPA for dash-separated non-CCPA US regions', () => {
|
|
308
|
-
const nonCcpaRegions = ['US-NY', 'US-TX', 'US-WA'];
|
|
309
|
-
|
|
310
|
-
for (const region of nonCcpaRegions) {
|
|
311
|
-
const jurisdiction = checkJurisdiction('US', region);
|
|
312
|
-
|
|
313
|
-
expect(jurisdiction).toBe('NONE');
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
});
|