@c15t/backend 2.0.0-rc.0 → 2.0.0-rc.2

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.
Files changed (49) hide show
  1. package/.turbo/turbo-build.log +11 -11
  2. package/CHANGELOG.md +20 -0
  3. package/dist/core.cjs +21 -24
  4. package/dist/core.js +21 -24
  5. package/dist/db/registry/index.d.ts +0 -1
  6. package/dist/db/registry/index.d.ts.map +1 -1
  7. package/dist/db/registry/subject.d.ts +0 -1
  8. package/dist/db/registry/subject.d.ts.map +1 -1
  9. package/dist/db/schema/1.0.0/index.d.ts +0 -31
  10. package/dist/db/schema/1.0.0/index.d.ts.map +1 -1
  11. package/dist/db/schema/1.0.0/subject.d.ts +0 -1
  12. package/dist/db/schema/1.0.0/subject.d.ts.map +1 -1
  13. package/dist/db/schema/2.0.0/consent.d.ts +2 -0
  14. package/dist/db/schema/2.0.0/consent.d.ts.map +1 -1
  15. package/dist/db/schema/2.0.0/index.d.ts +16 -11
  16. package/dist/db/schema/2.0.0/index.d.ts.map +1 -1
  17. package/dist/db/schema/2.0.0/subject.d.ts +0 -1
  18. package/dist/db/schema/2.0.0/subject.d.ts.map +1 -1
  19. package/dist/db/schema/index.d.ts +32 -53
  20. package/dist/db/schema/index.d.ts.map +1 -1
  21. package/dist/db/schema.cjs +1 -2
  22. package/dist/db/schema.js +1 -2
  23. package/dist/handlers/subject/get.handler.d.ts +0 -1
  24. package/dist/handlers/subject/get.handler.d.ts.map +1 -1
  25. package/dist/handlers/subject/list.handler.d.ts +0 -1
  26. package/dist/handlers/subject/list.handler.d.ts.map +1 -1
  27. package/dist/handlers/subject/patch.handler.d.ts +0 -1
  28. package/dist/handlers/subject/patch.handler.d.ts.map +1 -1
  29. package/dist/handlers/subject/post.handler.d.ts.map +1 -1
  30. package/dist/router.cjs +17 -16
  31. package/dist/router.js +17 -16
  32. package/dist/routes/init.d.ts.map +1 -1
  33. package/dist/types/index.d.ts +13 -5
  34. package/dist/types/index.d.ts.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/package.json +6 -6
  37. package/src/db/registry/subject.test.ts +1 -18
  38. package/src/db/registry/subject.ts +0 -3
  39. package/src/db/schema/1.0.0/subject.ts +0 -1
  40. package/src/db/schema/2.0.0/consent.ts +2 -0
  41. package/src/db/schema/2.0.0/subject.ts +0 -1
  42. package/src/db/tenant-scope.test.ts +10 -13
  43. package/src/handlers/subject/get.handler.ts +0 -1
  44. package/src/handlers/subject/list.handler.ts +0 -1
  45. package/src/handlers/subject/patch.handler.ts +0 -3
  46. package/src/handlers/subject/post.handler.ts +14 -0
  47. package/src/routes/init.ts +8 -5
  48. package/src/types/index.ts +14 -5
  49. package/src/version.ts +1 -1
@@ -150,14 +150,13 @@ describe('withTenantScope', () => {
150
150
  id: 'sub_1',
151
151
  externalId: null,
152
152
  identityProvider: 'anonymous',
153
- isIdentified: false,
154
153
  } as any);
155
154
 
156
155
  expect(db.create).toHaveBeenCalledWith('subject', {
157
156
  id: 'sub_1',
158
157
  externalId: null,
159
158
  identityProvider: 'anonymous',
160
- isIdentified: false,
159
+
161
160
  tenantId: 'tenant_abc',
162
161
  });
163
162
  });
@@ -169,13 +168,13 @@ describe('withTenantScope', () => {
169
168
  const scoped = withTenantScope(db, tenantId);
170
169
 
171
170
  await scoped.createMany('subject', [
172
- { id: 'sub_1', isIdentified: false } as any,
173
- { id: 'sub_2', isIdentified: true } as any,
171
+ { id: 'sub_1', externalId: null } as any,
172
+ { id: 'sub_2', externalId: 'ext_1' } as any,
174
173
  ]);
175
174
 
176
175
  expect(db.createMany).toHaveBeenCalledWith('subject', [
177
- { id: 'sub_1', isIdentified: false, tenantId: 'tenant_abc' },
178
- { id: 'sub_2', isIdentified: true, tenantId: 'tenant_abc' },
176
+ { id: 'sub_1', externalId: null, tenantId: 'tenant_abc' },
177
+ { id: 'sub_2', externalId: 'ext_1', tenantId: 'tenant_abc' },
179
178
  ]);
180
179
  });
181
180
  });
@@ -284,7 +283,7 @@ describe('withTenantScope', () => {
284
283
  const scoped = withTenantScope(db, tenantId);
285
284
 
286
285
  await scoped.count('subject', {
287
- where: (b: any) => b('isIdentified', '=', true),
286
+ where: (b: any) => b('externalId', '=', 'ext_1'),
288
287
  });
289
288
 
290
289
  const passedOpts = db.count.mock.calls[0][1];
@@ -295,9 +294,9 @@ describe('withTenantScope', () => {
295
294
  conditions: [
296
295
  {
297
296
  _type: 'condition',
298
- col: 'isIdentified',
297
+ col: 'externalId',
299
298
  op: '=',
300
- val: true,
299
+ val: 'ext_1',
301
300
  },
302
301
  {
303
302
  _type: 'condition',
@@ -380,7 +379,6 @@ describe('withTenantScope', () => {
380
379
  create: {
381
380
  id: 'sub_1',
382
381
  externalId: 'ext_1',
383
- isIdentified: true,
384
382
  } as any,
385
383
  update: { identityProvider: 'google' },
386
384
  });
@@ -391,7 +389,7 @@ describe('withTenantScope', () => {
391
389
  expect(passedOpts.create).toEqual({
392
390
  id: 'sub_1',
393
391
  externalId: 'ext_1',
394
- isIdentified: true,
392
+
395
393
  tenantId: 'tenant_abc',
396
394
  });
397
395
 
@@ -432,7 +430,6 @@ describe('withTenantScope', () => {
432
430
  await scoped.transaction(async (tx) => {
433
431
  await tx.create('subject', {
434
432
  id: 'sub_1',
435
- isIdentified: false,
436
433
  } as any);
437
434
  await tx.findFirst('subject', {
438
435
  where: (b: any) => b('id', '=', 'sub_1'),
@@ -442,7 +439,7 @@ describe('withTenantScope', () => {
442
439
  // The inner db should have tenantId injected
443
440
  expect(innerDb.create).toHaveBeenCalledWith('subject', {
444
441
  id: 'sub_1',
445
- isIdentified: false,
442
+
446
443
  tenantId: 'tenant_abc',
447
444
  });
448
445
 
@@ -69,7 +69,6 @@ export const getSubjectHandler = async (c: Context) => {
69
69
  subject: {
70
70
  id: subject.id,
71
71
  externalId: subject.externalId ?? undefined,
72
- isIdentified: subject.isIdentified,
73
72
  createdAt: subject.createdAt,
74
73
  },
75
74
  consents: filteredConsents,
@@ -60,7 +60,6 @@ export const listSubjectsHandler = async (c: Context) => {
60
60
  return {
61
61
  id: subject.id,
62
62
  externalId: subject.externalId ?? externalId,
63
- isIdentified: subject.isIdentified,
64
63
  createdAt: subject.createdAt,
65
64
  consents: consentItems,
66
65
  };
@@ -59,7 +59,6 @@ export const patchSubjectHandler = async (c: Context) => {
59
59
  set: {
60
60
  externalId,
61
61
  identityProvider,
62
- isIdentified: true,
63
62
  updatedAt: new Date(),
64
63
  },
65
64
  });
@@ -79,7 +78,6 @@ export const patchSubjectHandler = async (c: Context) => {
79
78
  from: subject.identityProvider,
80
79
  to: identityProvider,
81
80
  },
82
- isIdentified: { from: subject.isIdentified, to: true },
83
81
  },
84
82
  metadata: {
85
83
  externalId,
@@ -101,7 +99,6 @@ export const patchSubjectHandler = async (c: Context) => {
101
99
  subject: {
102
100
  id: subjectId,
103
101
  externalId,
104
- isIdentified: true,
105
102
  },
106
103
  });
107
104
  } catch (error) {
@@ -40,6 +40,19 @@ export const postSubjectHandler = async (c: Context) => {
40
40
  const preferences = 'preferences' in input ? input.preferences : undefined;
41
41
  const givenAt = new Date(givenAtEpoch);
42
42
 
43
+ // Derive model-aware consent action from the raw frontend type
44
+ const rawConsentAction =
45
+ 'consentAction' in input ? input.consentAction : undefined;
46
+ let derivedConsentAction: string | undefined;
47
+ if (rawConsentAction === 'all') {
48
+ derivedConsentAction = 'accept_all';
49
+ } else if (rawConsentAction === 'necessary') {
50
+ derivedConsentAction =
51
+ input.jurisdictionModel === 'opt-out' ? 'opt_out' : 'reject_all';
52
+ } else if (rawConsentAction === 'custom') {
53
+ derivedConsentAction = 'custom';
54
+ }
55
+
43
56
  logger.debug('Request parameters', {
44
57
  type,
45
58
  subjectId,
@@ -188,6 +201,7 @@ export const postSubjectHandler = async (c: Context) => {
188
201
  jurisdictionModel: input.jurisdictionModel,
189
202
  tcString: input.tcString,
190
203
  uiSource: input.uiSource,
204
+ consentAction: derivedConsentAction,
191
205
  givenAt,
192
206
  });
193
207
 
@@ -63,20 +63,20 @@ Use for geo-targeted consent banners and regional compliance.`,
63
63
 
64
64
  // Get GVL if enabled
65
65
  let gvl = null;
66
- if (options.advanced?.gvl?.enabled) {
66
+ if (options.advanced?.iab?.enabled) {
67
67
  const language = translationsResult.language.split('-')[0] || 'en';
68
68
  const gvlResolver = createGVLResolver({
69
69
  appName: options.appName || 'c15t',
70
- bundled: options.advanced.gvl.bundled,
70
+ bundled: options.advanced.iab.bundled,
71
71
  cacheAdapter: options.advanced.cache?.adapter,
72
- vendorIds: options.advanced.gvl.vendorIds,
73
- endpoint: options.advanced.gvl.endpoint,
72
+ vendorIds: options.advanced.iab.vendorIds,
73
+ endpoint: options.advanced.iab.endpoint,
74
74
  });
75
75
  gvl = await gvlResolver.get(language);
76
76
  }
77
77
 
78
78
  // Get custom vendors if configured
79
- const customVendors = options.advanced?.gvl?.customVendors;
79
+ const customVendors = options.advanced?.iab?.customVendors;
80
80
 
81
81
  // Record init metric
82
82
  const gpc = request.headers.get('sec-gpc') === '1';
@@ -94,6 +94,9 @@ Use for geo-targeted consent banners and regional compliance.`,
94
94
  branding: options.advanced?.branding || 'c15t',
95
95
  gvl,
96
96
  customVendors,
97
+ ...(options.advanced?.iab?.cmpId != null && {
98
+ cmpId: options.advanced.iab.cmpId,
99
+ }),
97
100
  });
98
101
  }
99
102
  );
@@ -182,17 +182,26 @@ export interface AdvancedOptions {
182
182
  apiKeys?: string[];
183
183
 
184
184
  /**
185
- * GVL (Global Vendor List) configuration for IAB TCF compliance.
185
+ * IAB TCF configuration including GVL, CMP registration, and custom vendors.
186
186
  * Disabled by default - most users don't need IAB TCF.
187
- * Set enabled: true to activate GVL support.
187
+ * Set enabled: true to activate IAB support.
188
188
  */
189
- gvl?: {
189
+ iab?: {
190
190
  /**
191
- * Enable GVL support.
191
+ * Enable IAB TCF support.
192
192
  * When false or not provided, /init returns gvl: null.
193
193
  */
194
194
  enabled: true;
195
195
 
196
+ /**
197
+ * CMP ID registered with IAB Europe.
198
+ * This is returned to clients via the /init endpoint so they
199
+ * can use the correct CMP identity in TC Strings.
200
+ *
201
+ * @see https://iabeurope.eu/cmp-list/ - List of registered CMPs
202
+ */
203
+ cmpId?: number;
204
+
196
205
  /**
197
206
  * Bundled GVL translations by language code.
198
207
  * These are checked first before any cache or fetch.
@@ -202,7 +211,7 @@ export interface AdvancedOptions {
202
211
  * import enGVL from './gvl/en.json';
203
212
  * import deGVL from './gvl/de.json';
204
213
  *
205
- * gvl: {
214
+ * iab: {
206
215
  * enabled: true,
207
216
  * bundled: { en: enGVL, de: deGVL }
208
217
  * }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '2.0.0-rc.0';
2
+ export const version = '2.0.0-rc.2';