@c15t/backend 2.0.0-rc.5 → 2.0.0-rc.6
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/dist/302.js +473 -0
- package/dist/364.js +1140 -0
- package/dist/583.js +540 -0
- package/dist/cache.cjs +1 -1
- package/dist/cache.js +4 -415
- package/dist/core.cjs +21 -24
- package/dist/core.js +18 -2420
- 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 +1 -1
- package/dist/db/schema.js +1 -1
- package/dist/define-config.cjs +1 -1
- package/dist/edge.cjs +1 -1
- package/dist/edge.js +3 -882
- package/dist/router.cjs +17 -18
- package/dist/router.js +1 -2058
- package/dist/types/index.cjs +1 -1
- package/dist-types/cache/gvl-resolver.d.ts +1 -1
- package/dist-types/db/registry/runtime-policy-decision.d.ts +1 -1
- package/dist-types/db/schema/1.0.0/consent.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/audit-log.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent-policy.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent-purpose.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/domain.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/subject.d.ts +1 -1
- package/dist-types/handlers/init/index.d.ts +1 -1
- package/dist-types/handlers/init/policy.d.ts +1 -1
- package/dist-types/handlers/init/resolve-init.d.ts +1 -1
- package/dist-types/handlers/policy/snapshot.d.ts +1 -1
- package/dist-types/policies/defaults.d.ts +1 -1
- package/dist-types/policies/matchers.d.ts +2 -2
- package/dist-types/types/index.d.ts +2 -2
- package/dist-types/version.d.ts +1 -1
- package/docs/guides/policy-packs.md +1 -1
- package/package.json +15 -15
package/dist/cache.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Redis } from "@upstash/redis";
|
|
2
|
-
import {
|
|
3
|
-
const GVL_TTL_MS = 259200000;
|
|
2
|
+
import { GVL_TTL_MS } from "./302.js";
|
|
4
3
|
function createCloudflareKVAdapter(kv) {
|
|
5
4
|
return {
|
|
6
5
|
async get (key) {
|
|
@@ -24,44 +23,6 @@ function createCloudflareKVAdapter(kv) {
|
|
|
24
23
|
}
|
|
25
24
|
};
|
|
26
25
|
}
|
|
27
|
-
const memory_memoryCache = new Map();
|
|
28
|
-
function createMemoryCacheAdapter() {
|
|
29
|
-
return {
|
|
30
|
-
async get (key) {
|
|
31
|
-
const entry = memory_memoryCache.get(key);
|
|
32
|
-
if (!entry) return null;
|
|
33
|
-
if (Date.now() > entry.expiresAt) {
|
|
34
|
-
memory_memoryCache.delete(key);
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
return entry.value;
|
|
38
|
-
},
|
|
39
|
-
async set (key, value, ttlMs = 300000) {
|
|
40
|
-
memory_memoryCache.set(key, {
|
|
41
|
-
value,
|
|
42
|
-
expiresAt: Date.now() + ttlMs
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
|
-
async delete (key) {
|
|
46
|
-
memory_memoryCache.delete(key);
|
|
47
|
-
},
|
|
48
|
-
async has (key) {
|
|
49
|
-
const entry = memory_memoryCache.get(key);
|
|
50
|
-
if (!entry) return false;
|
|
51
|
-
if (Date.now() > entry.expiresAt) {
|
|
52
|
-
memory_memoryCache.delete(key);
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function clearMemoryCache() {
|
|
60
|
-
memory_memoryCache.clear();
|
|
61
|
-
}
|
|
62
|
-
function getMemoryCacheSize() {
|
|
63
|
-
return memory_memoryCache.size;
|
|
64
|
-
}
|
|
65
26
|
function createUpstashRedisAdapter(options) {
|
|
66
27
|
const client = new Redis({
|
|
67
28
|
url: options.url,
|
|
@@ -90,378 +51,6 @@ function createUpstashRedisAdapterFromClient(client) {
|
|
|
90
51
|
}
|
|
91
52
|
};
|
|
92
53
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return `AggregateError: ${inner}`;
|
|
97
|
-
}
|
|
98
|
-
if (error instanceof Error) return error.message || error.name;
|
|
99
|
-
return String(error);
|
|
100
|
-
}
|
|
101
|
-
let cachedConfig = null;
|
|
102
|
-
let cachedDefaultAttributes = {};
|
|
103
|
-
function create_telemetry_options_isTelemetryEnabled(options) {
|
|
104
|
-
if (options) return options.telemetry?.enabled === true;
|
|
105
|
-
return cachedConfig?.enabled === true;
|
|
106
|
-
}
|
|
107
|
-
const create_telemetry_options_getTracer = (options)=>{
|
|
108
|
-
if (!create_telemetry_options_isTelemetryEnabled(options)) return api_trace.getTracer('c15t-noop');
|
|
109
|
-
const tracer = options?.telemetry?.tracer ?? cachedConfig?.tracer;
|
|
110
|
-
if (tracer) return tracer;
|
|
111
|
-
return api_trace.getTracer(options?.appName ?? 'c15t');
|
|
112
|
-
};
|
|
113
|
-
const getMeter = (options)=>{
|
|
114
|
-
if (!create_telemetry_options_isTelemetryEnabled(options)) return metrics.getMeter('c15t-noop');
|
|
115
|
-
const meter = options?.telemetry?.meter ?? cachedConfig?.meter;
|
|
116
|
-
if (meter) return meter;
|
|
117
|
-
return metrics.getMeter(options?.appName ?? 'c15t');
|
|
118
|
-
};
|
|
119
|
-
function getDefaultAttributes() {
|
|
120
|
-
return cachedDefaultAttributes;
|
|
121
|
-
}
|
|
122
|
-
const handleSpanError = (span, error)=>{
|
|
123
|
-
span.setStatus({
|
|
124
|
-
code: api_SpanStatusCode.ERROR,
|
|
125
|
-
message: extractErrorMessage(error)
|
|
126
|
-
});
|
|
127
|
-
if (error instanceof Error) span.setAttribute('error.type', error.name);
|
|
128
|
-
};
|
|
129
|
-
const withSpanContext = async (span, operation)=>context["with"](api_trace.setSpan(context.active(), span), operation);
|
|
130
|
-
async function executeWithSpan(span, operation) {
|
|
131
|
-
try {
|
|
132
|
-
const result = await withSpanContext(span, operation);
|
|
133
|
-
span.setStatus({
|
|
134
|
-
code: api_SpanStatusCode.OK
|
|
135
|
-
});
|
|
136
|
-
return result;
|
|
137
|
-
} catch (error) {
|
|
138
|
-
handleSpanError(span, error);
|
|
139
|
-
throw error;
|
|
140
|
-
} finally{
|
|
141
|
-
span.end();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function resolveDefaultAttributes(options) {
|
|
145
|
-
return options?.telemetry?.defaultAttributes || getDefaultAttributes();
|
|
146
|
-
}
|
|
147
|
-
async function withExternalSpan(attributes, operation, options) {
|
|
148
|
-
if (!create_telemetry_options_isTelemetryEnabled(options)) return operation();
|
|
149
|
-
const tracer = create_telemetry_options_getTracer(options);
|
|
150
|
-
const url = new URL(attributes.url);
|
|
151
|
-
const spanName = `HTTP ${attributes.method} ${url.hostname}`;
|
|
152
|
-
const span = tracer.startSpan(spanName, {
|
|
153
|
-
kind: api_SpanKind.CLIENT,
|
|
154
|
-
attributes: {
|
|
155
|
-
'http.method': attributes.method,
|
|
156
|
-
'http.url': `${url.origin}${url.pathname}`,
|
|
157
|
-
'http.host': url.hostname,
|
|
158
|
-
...resolveDefaultAttributes(options),
|
|
159
|
-
...Object.fromEntries(Object.entries(attributes).filter(([key])=>![
|
|
160
|
-
'url',
|
|
161
|
-
'method'
|
|
162
|
-
].includes(key)))
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
return executeWithSpan(span, operation);
|
|
166
|
-
}
|
|
167
|
-
async function withCacheSpan(operation, layer, fn, options) {
|
|
168
|
-
if (!create_telemetry_options_isTelemetryEnabled(options)) return fn();
|
|
169
|
-
const tracer = create_telemetry_options_getTracer(options);
|
|
170
|
-
const spanName = `cache.${layer}.${operation}`;
|
|
171
|
-
const span = tracer.startSpan(spanName, {
|
|
172
|
-
kind: api_SpanKind.CLIENT,
|
|
173
|
-
attributes: {
|
|
174
|
-
'cache.operation': operation,
|
|
175
|
-
'cache.layer': layer,
|
|
176
|
-
...resolveDefaultAttributes(options)
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
return executeWithSpan(span, fn);
|
|
180
|
-
}
|
|
181
|
-
function sanitizeAttributes(attrs) {
|
|
182
|
-
return Object.fromEntries(Object.entries(attrs).filter(([_, v])=>null != v));
|
|
183
|
-
}
|
|
184
|
-
function createMetrics(meter) {
|
|
185
|
-
const consentCreated = meter.createCounter('c15t.consent.created', {
|
|
186
|
-
description: 'Number of consent submissions',
|
|
187
|
-
unit: '1'
|
|
188
|
-
});
|
|
189
|
-
const consentAccepted = meter.createCounter('c15t.consent.accepted', {
|
|
190
|
-
description: 'Number of consents accepted',
|
|
191
|
-
unit: '1'
|
|
192
|
-
});
|
|
193
|
-
const consentRejected = meter.createCounter('c15t.consent.rejected', {
|
|
194
|
-
description: 'Number of consents rejected',
|
|
195
|
-
unit: '1'
|
|
196
|
-
});
|
|
197
|
-
const subjectCreated = meter.createCounter('c15t.subject.created', {
|
|
198
|
-
description: 'Number of new subjects created',
|
|
199
|
-
unit: '1'
|
|
200
|
-
});
|
|
201
|
-
const subjectLinked = meter.createCounter('c15t.subject.linked', {
|
|
202
|
-
description: 'Number of subjects linked to external ID',
|
|
203
|
-
unit: '1'
|
|
204
|
-
});
|
|
205
|
-
const consentCheckCount = meter.createCounter('c15t.consent_check.count', {
|
|
206
|
-
description: 'Number of cross-device consent checks',
|
|
207
|
-
unit: '1'
|
|
208
|
-
});
|
|
209
|
-
const initCount = meter.createCounter('c15t.init.count', {
|
|
210
|
-
description: 'Number of init endpoint calls',
|
|
211
|
-
unit: '1'
|
|
212
|
-
});
|
|
213
|
-
const httpRequestDuration = meter.createHistogram('c15t.http.request.duration', {
|
|
214
|
-
description: 'HTTP request latency',
|
|
215
|
-
unit: 'ms'
|
|
216
|
-
});
|
|
217
|
-
const httpRequestCount = meter.createCounter('c15t.http.request.count', {
|
|
218
|
-
description: 'Number of HTTP requests',
|
|
219
|
-
unit: '1'
|
|
220
|
-
});
|
|
221
|
-
const httpErrorCount = meter.createCounter('c15t.http.error.count', {
|
|
222
|
-
description: 'Number of HTTP errors',
|
|
223
|
-
unit: '1'
|
|
224
|
-
});
|
|
225
|
-
const dbQueryDuration = meter.createHistogram('c15t.db.query.duration', {
|
|
226
|
-
description: 'Database query latency',
|
|
227
|
-
unit: 'ms'
|
|
228
|
-
});
|
|
229
|
-
const dbQueryCount = meter.createCounter('c15t.db.query.count', {
|
|
230
|
-
description: 'Number of database queries',
|
|
231
|
-
unit: '1'
|
|
232
|
-
});
|
|
233
|
-
const dbErrorCount = meter.createCounter('c15t.db.error.count', {
|
|
234
|
-
description: 'Number of database errors',
|
|
235
|
-
unit: '1'
|
|
236
|
-
});
|
|
237
|
-
const cacheHit = meter.createCounter('c15t.cache.hit', {
|
|
238
|
-
description: 'Number of cache hits',
|
|
239
|
-
unit: '1'
|
|
240
|
-
});
|
|
241
|
-
const cacheMiss = meter.createCounter('c15t.cache.miss', {
|
|
242
|
-
description: 'Number of cache misses',
|
|
243
|
-
unit: '1'
|
|
244
|
-
});
|
|
245
|
-
const cacheLatency = meter.createHistogram('c15t.cache.latency', {
|
|
246
|
-
description: 'Cache operation latency',
|
|
247
|
-
unit: 'ms'
|
|
248
|
-
});
|
|
249
|
-
const gvlFetchDuration = meter.createHistogram('c15t.gvl.fetch.duration', {
|
|
250
|
-
description: 'GVL fetch latency',
|
|
251
|
-
unit: 'ms'
|
|
252
|
-
});
|
|
253
|
-
const gvlFetchCount = meter.createCounter('c15t.gvl.fetch.count', {
|
|
254
|
-
description: 'Number of GVL fetches',
|
|
255
|
-
unit: '1'
|
|
256
|
-
});
|
|
257
|
-
const gvlFetchError = meter.createCounter('c15t.gvl.fetch.error', {
|
|
258
|
-
description: 'Number of GVL fetch errors',
|
|
259
|
-
unit: '1'
|
|
260
|
-
});
|
|
261
|
-
return {
|
|
262
|
-
consentCreated,
|
|
263
|
-
consentAccepted,
|
|
264
|
-
consentRejected,
|
|
265
|
-
subjectCreated,
|
|
266
|
-
subjectLinked,
|
|
267
|
-
consentCheckCount,
|
|
268
|
-
initCount,
|
|
269
|
-
httpRequestDuration,
|
|
270
|
-
httpRequestCount,
|
|
271
|
-
httpErrorCount,
|
|
272
|
-
dbQueryDuration,
|
|
273
|
-
dbQueryCount,
|
|
274
|
-
dbErrorCount,
|
|
275
|
-
cacheHit,
|
|
276
|
-
cacheMiss,
|
|
277
|
-
cacheLatency,
|
|
278
|
-
gvlFetchDuration,
|
|
279
|
-
gvlFetchCount,
|
|
280
|
-
gvlFetchError,
|
|
281
|
-
recordConsentCreated (attributes) {
|
|
282
|
-
consentCreated.add(1, sanitizeAttributes(attributes));
|
|
283
|
-
},
|
|
284
|
-
recordConsentAccepted (attributes) {
|
|
285
|
-
consentAccepted.add(1, sanitizeAttributes(attributes));
|
|
286
|
-
},
|
|
287
|
-
recordConsentRejected (attributes) {
|
|
288
|
-
consentRejected.add(1, sanitizeAttributes(attributes));
|
|
289
|
-
},
|
|
290
|
-
recordSubjectCreated (attributes) {
|
|
291
|
-
subjectCreated.add(1, sanitizeAttributes(attributes));
|
|
292
|
-
},
|
|
293
|
-
recordSubjectLinked (identityProvider) {
|
|
294
|
-
subjectLinked.add(1, {
|
|
295
|
-
identityProvider: identityProvider || 'unknown'
|
|
296
|
-
});
|
|
297
|
-
},
|
|
298
|
-
recordConsentCheck (type, found) {
|
|
299
|
-
consentCheckCount.add(1, {
|
|
300
|
-
type,
|
|
301
|
-
found: String(found)
|
|
302
|
-
});
|
|
303
|
-
},
|
|
304
|
-
recordInit (attributes) {
|
|
305
|
-
initCount.add(1, sanitizeAttributes(attributes));
|
|
306
|
-
},
|
|
307
|
-
recordHttpRequest (attributes, durationMs) {
|
|
308
|
-
const attrs = sanitizeAttributes(attributes);
|
|
309
|
-
httpRequestCount.add(1, attrs);
|
|
310
|
-
httpRequestDuration.record(durationMs, attrs);
|
|
311
|
-
if (attributes.status >= 400) httpErrorCount.add(1, attrs);
|
|
312
|
-
},
|
|
313
|
-
recordDbQuery (attributes, durationMs) {
|
|
314
|
-
const attrs = sanitizeAttributes(attributes);
|
|
315
|
-
dbQueryCount.add(1, attrs);
|
|
316
|
-
dbQueryDuration.record(durationMs, attrs);
|
|
317
|
-
},
|
|
318
|
-
recordDbError (attributes) {
|
|
319
|
-
dbErrorCount.add(1, sanitizeAttributes(attributes));
|
|
320
|
-
},
|
|
321
|
-
recordCacheHit (layer) {
|
|
322
|
-
cacheHit.add(1, {
|
|
323
|
-
layer
|
|
324
|
-
});
|
|
325
|
-
},
|
|
326
|
-
recordCacheMiss (layer) {
|
|
327
|
-
cacheMiss.add(1, {
|
|
328
|
-
layer
|
|
329
|
-
});
|
|
330
|
-
},
|
|
331
|
-
recordCacheLatency (attributes, durationMs) {
|
|
332
|
-
cacheLatency.record(durationMs, sanitizeAttributes(attributes));
|
|
333
|
-
},
|
|
334
|
-
recordGvlFetch (attributes, durationMs) {
|
|
335
|
-
const attrs = sanitizeAttributes(attributes);
|
|
336
|
-
gvlFetchCount.add(1, attrs);
|
|
337
|
-
gvlFetchDuration.record(durationMs, attrs);
|
|
338
|
-
},
|
|
339
|
-
recordGvlError (attributes) {
|
|
340
|
-
gvlFetchError.add(1, sanitizeAttributes(attributes));
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
let metricsInstance = null;
|
|
345
|
-
function getMetrics(options) {
|
|
346
|
-
if (metricsInstance) return metricsInstance;
|
|
347
|
-
if (!create_telemetry_options_isTelemetryEnabled(options)) return null;
|
|
348
|
-
metricsInstance = createMetrics(getMeter(options));
|
|
349
|
-
return metricsInstance;
|
|
350
|
-
}
|
|
351
|
-
function createGVLCacheKey(appName, language, vendorIds) {
|
|
352
|
-
const sortedIds = vendorIds ? [
|
|
353
|
-
...vendorIds
|
|
354
|
-
].sort((a, b)=>a - b).join(',') : 'all';
|
|
355
|
-
return `${appName}:gvl:${language}:${sortedIds}`;
|
|
356
|
-
}
|
|
357
|
-
function createCacheKey(appName, namespace, ...parts) {
|
|
358
|
-
const allParts = [
|
|
359
|
-
appName,
|
|
360
|
-
namespace,
|
|
361
|
-
...parts
|
|
362
|
-
];
|
|
363
|
-
return allParts.join(':');
|
|
364
|
-
}
|
|
365
|
-
const GVL_ENDPOINT = 'https://gvl.consent.io';
|
|
366
|
-
const inflightRequests = new Map();
|
|
367
|
-
async function fetchGVLWithLanguage(language, vendorIds, endpoint = GVL_ENDPOINT) {
|
|
368
|
-
const sortedVendorIds = vendorIds ? [
|
|
369
|
-
...vendorIds
|
|
370
|
-
].sort((a, b)=>a - b) : [];
|
|
371
|
-
const dedupeKey = `${endpoint}|${language}|${sortedVendorIds.join(',')}`;
|
|
372
|
-
const existingRequest = inflightRequests.get(dedupeKey);
|
|
373
|
-
if (existingRequest) return existingRequest;
|
|
374
|
-
const url = new URL(endpoint);
|
|
375
|
-
if (sortedVendorIds.length > 0) url.searchParams.set('vendorIds', sortedVendorIds.join(','));
|
|
376
|
-
const promise = (async ()=>{
|
|
377
|
-
const fetchStart = Date.now();
|
|
378
|
-
try {
|
|
379
|
-
const gvl = await withExternalSpan({
|
|
380
|
-
url: url.toString(),
|
|
381
|
-
method: 'GET'
|
|
382
|
-
}, async ()=>{
|
|
383
|
-
const response = await fetch(url.toString(), {
|
|
384
|
-
headers: {
|
|
385
|
-
'Accept-Language': language
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
if (204 === response.status) return null;
|
|
389
|
-
if (!response.ok) throw new Error(`Failed to fetch GVL: ${response.status} ${response.statusText}`);
|
|
390
|
-
const text = await response.text();
|
|
391
|
-
const trimmed = text.trim().replace(/^\uFEFF/, '');
|
|
392
|
-
let parsed;
|
|
393
|
-
try {
|
|
394
|
-
parsed = JSON.parse(trimmed);
|
|
395
|
-
} catch {
|
|
396
|
-
let depth = 0;
|
|
397
|
-
let end = -1;
|
|
398
|
-
const start = trimmed.indexOf('{');
|
|
399
|
-
if (start >= 0) for(let i = start; i < trimmed.length; i++){
|
|
400
|
-
const c = trimmed[i];
|
|
401
|
-
if ('{' === c) depth++;
|
|
402
|
-
else if ('}' === c) {
|
|
403
|
-
depth--;
|
|
404
|
-
if (0 === depth) {
|
|
405
|
-
end = i + 1;
|
|
406
|
-
break;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
if (end > 0) parsed = JSON.parse(trimmed.slice(0, end));
|
|
411
|
-
else throw new SyntaxError('Invalid GVL response: not valid JSON');
|
|
412
|
-
}
|
|
413
|
-
if (!parsed.vendorListVersion || !parsed.purposes || !parsed.vendors) throw new Error('Invalid GVL response: missing required fields');
|
|
414
|
-
return parsed;
|
|
415
|
-
});
|
|
416
|
-
getMetrics()?.recordGvlFetch({
|
|
417
|
-
language,
|
|
418
|
-
source: 'fetch',
|
|
419
|
-
status: 200
|
|
420
|
-
}, Date.now() - fetchStart);
|
|
421
|
-
return gvl;
|
|
422
|
-
} catch (error) {
|
|
423
|
-
getMetrics()?.recordGvlError({
|
|
424
|
-
language,
|
|
425
|
-
errorType: error instanceof Error ? error.name : 'UnknownError'
|
|
426
|
-
});
|
|
427
|
-
throw error;
|
|
428
|
-
} finally{
|
|
429
|
-
inflightRequests.delete(dedupeKey);
|
|
430
|
-
}
|
|
431
|
-
})();
|
|
432
|
-
inflightRequests.set(dedupeKey, promise);
|
|
433
|
-
return promise;
|
|
434
|
-
}
|
|
435
|
-
function createGVLResolver(options) {
|
|
436
|
-
const { appName, bundled, cacheAdapter, vendorIds, endpoint } = options;
|
|
437
|
-
const memoryCache = createMemoryCacheAdapter();
|
|
438
|
-
return {
|
|
439
|
-
async get (language) {
|
|
440
|
-
const cacheKey = createGVLCacheKey(appName, language, vendorIds);
|
|
441
|
-
if (bundled?.[language]) return bundled[language];
|
|
442
|
-
const memoryHit = await withCacheSpan('get', 'memory', ()=>memoryCache.get(cacheKey));
|
|
443
|
-
if (memoryHit) {
|
|
444
|
-
getMetrics()?.recordCacheHit('memory');
|
|
445
|
-
return memoryHit;
|
|
446
|
-
}
|
|
447
|
-
getMetrics()?.recordCacheMiss('memory');
|
|
448
|
-
if (cacheAdapter) {
|
|
449
|
-
const externalHit = await withCacheSpan('get', 'external', ()=>cacheAdapter.get(cacheKey));
|
|
450
|
-
if (externalHit) {
|
|
451
|
-
getMetrics()?.recordCacheHit('external');
|
|
452
|
-
await withCacheSpan('set', 'memory', ()=>memoryCache.set(cacheKey, externalHit, 300000));
|
|
453
|
-
return externalHit;
|
|
454
|
-
}
|
|
455
|
-
getMetrics()?.recordCacheMiss('external');
|
|
456
|
-
}
|
|
457
|
-
const gvl = await fetchGVLWithLanguage(language, vendorIds, endpoint);
|
|
458
|
-
if (gvl) {
|
|
459
|
-
await withCacheSpan('set', 'memory', ()=>memoryCache.set(cacheKey, gvl, 300000));
|
|
460
|
-
if (cacheAdapter) await withCacheSpan('set', 'external', ()=>cacheAdapter.set(cacheKey, gvl, GVL_TTL_MS));
|
|
461
|
-
}
|
|
462
|
-
return gvl;
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
var __webpack_exports__MEMORY_TTL_MS = 300000;
|
|
467
|
-
export { GVL_TTL_MS, clearMemoryCache, createCacheKey, createCloudflareKVAdapter, createGVLCacheKey, createGVLResolver, createMemoryCacheAdapter, createUpstashRedisAdapter, createUpstashRedisAdapterFromClient, getMemoryCacheSize, __webpack_exports__MEMORY_TTL_MS as MEMORY_TTL_MS };
|
|
54
|
+
var cache_MEMORY_TTL_MS = 300000;
|
|
55
|
+
export { GVL_TTL_MS, clearMemoryCache, createCacheKey, createGVLCacheKey, createGVLResolver, createMemoryCacheAdapter, getMemoryCacheSize } from "./302.js";
|
|
56
|
+
export { cache_MEMORY_TTL_MS as MEMORY_TTL_MS, createCloudflareKVAdapter, createUpstashRedisAdapter, createUpstashRedisAdapterFromClient };
|
package/dist/core.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __webpack_modules__ = {
|
|
3
|
-
"./src/db/schema/index.ts" (
|
|
3
|
+
"./src/db/schema/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
4
4
|
__webpack_require__.d(__webpack_exports__, {
|
|
5
5
|
DB: ()=>DB
|
|
6
6
|
});
|
|
@@ -294,7 +294,7 @@ var __webpack_modules__ = {
|
|
|
294
294
|
]
|
|
295
295
|
});
|
|
296
296
|
},
|
|
297
|
-
"./src/define-config.ts" (
|
|
297
|
+
"./src/define-config.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
298
298
|
__webpack_require__.d(__webpack_exports__, {
|
|
299
299
|
defineConfig: ()=>defineConfig
|
|
300
300
|
});
|
|
@@ -336,7 +336,7 @@ function __webpack_require__(moduleId) {
|
|
|
336
336
|
})();
|
|
337
337
|
(()=>{
|
|
338
338
|
__webpack_require__.r = (exports1)=>{
|
|
339
|
-
if (
|
|
339
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
340
340
|
value: 'Module'
|
|
341
341
|
});
|
|
342
342
|
Object.defineProperty(exports1, '__esModule', {
|
|
@@ -737,7 +737,7 @@ var __webpack_exports__ = {};
|
|
|
737
737
|
language
|
|
738
738
|
};
|
|
739
739
|
}
|
|
740
|
-
const version_version = '2.0.0-rc.
|
|
740
|
+
const version_version = '2.0.0-rc.6';
|
|
741
741
|
function extractErrorMessage(error) {
|
|
742
742
|
if (error instanceof AggregateError && error.errors?.length > 0) {
|
|
743
743
|
const inner = error.errors.map((e)=>e instanceof Error ? e.message : String(e)).join('; ');
|
|
@@ -1772,11 +1772,7 @@ var __webpack_exports__ = {};
|
|
|
1772
1772
|
const app = new external_hono_namespaceObject.Hono();
|
|
1773
1773
|
app.get('/check', (0, external_hono_openapi_namespaceObject.describeRoute)({
|
|
1774
1774
|
summary: 'Check consent by external user ID',
|
|
1775
|
-
description:
|
|
1776
|
-
|
|
1777
|
-
**Query parameters:**
|
|
1778
|
-
- \`externalId\` – External user ID to check
|
|
1779
|
-
- \`type\` – Consent type(s) to check (comma-separated)`,
|
|
1775
|
+
description: "Pre-banner cross-device consent check. Use to avoid showing the banner when the user has already consented on another device.\n\n**Query parameters:**\n- `externalId` – External user ID to check\n- `type` – Consent type(s) to check (comma-separated)",
|
|
1780
1776
|
tags: [
|
|
1781
1777
|
'Consent'
|
|
1782
1778
|
],
|
|
@@ -2442,6 +2438,12 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
2442
2438
|
const subjectId = c.req.param('id');
|
|
2443
2439
|
const type = c.req.query('type');
|
|
2444
2440
|
const typeFilter = type?.split(',').map((t)=>t.trim()) || [];
|
|
2441
|
+
if (!subjectId) throw new http_exception_namespaceObject.HTTPException(400, {
|
|
2442
|
+
message: 'Subject ID is required',
|
|
2443
|
+
cause: {
|
|
2444
|
+
code: 'SUBJECT_ID_REQUIRED'
|
|
2445
|
+
}
|
|
2446
|
+
});
|
|
2445
2447
|
logger.debug('Request parameters', {
|
|
2446
2448
|
subjectId,
|
|
2447
2449
|
typeFilter
|
|
@@ -2633,6 +2635,12 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
2633
2635
|
const subjectId = c.req.param('id');
|
|
2634
2636
|
const body = await c.req.json();
|
|
2635
2637
|
const { externalId, identityProvider = 'external' } = body;
|
|
2638
|
+
if (!subjectId) throw new http_exception_namespaceObject.HTTPException(400, {
|
|
2639
|
+
message: 'Subject ID is required',
|
|
2640
|
+
cause: {
|
|
2641
|
+
code: 'SUBJECT_ID_REQUIRED'
|
|
2642
|
+
}
|
|
2643
|
+
});
|
|
2636
2644
|
logger.debug('Request parameters', {
|
|
2637
2645
|
subjectId,
|
|
2638
2646
|
externalId,
|
|
@@ -3150,11 +3158,7 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
3150
3158
|
const app = new external_hono_namespaceObject.Hono();
|
|
3151
3159
|
app.get('/:id', (0, external_hono_openapi_namespaceObject.describeRoute)({
|
|
3152
3160
|
summary: 'Get subject consent status',
|
|
3153
|
-
description:
|
|
3154
|
-
|
|
3155
|
-
**Query:** \`type\` – Filter by consent type(s), comma-separated (e.g. \`privacy_policy,cookie_banner\`).
|
|
3156
|
-
|
|
3157
|
-
**Response:** \`subject\`, \`consents\` (matching filter), \`isValid\` (valid consent for requested type(s)).`,
|
|
3161
|
+
description: "Returns the subject's consent status for this device. Use to check if the subject has valid consent for given policy types.\n\n**Query:** `type` – Filter by consent type(s), comma-separated (e.g. `privacy_policy,cookie_banner`).\n\n**Response:** `subject`, `consents` (matching filter), `isValid` (valid consent for requested type(s)).",
|
|
3158
3162
|
tags: [
|
|
3159
3163
|
'Subject',
|
|
3160
3164
|
'Consent'
|
|
@@ -3175,12 +3179,7 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
3175
3179
|
}), (0, external_hono_openapi_namespaceObject.validator)('param', schema_.getSubjectInputSchema), getSubjectHandler);
|
|
3176
3180
|
app.post('/', (0, external_hono_openapi_namespaceObject.describeRoute)({
|
|
3177
3181
|
summary: 'Record consent for a subject',
|
|
3178
|
-
description:
|
|
3179
|
-
|
|
3180
|
-
**Request body by \`type\`:**
|
|
3181
|
-
- \`cookie_banner\` – Requires \`preferences\` object
|
|
3182
|
-
- \`privacy_policy\`, \`dpa\`, \`terms_and_conditions\` – Optional \`policyId\`
|
|
3183
|
-
- \`marketing_communications\`, \`age_verification\`, \`other\` – Optional \`preferences\``,
|
|
3182
|
+
description: "Creates a new consent record (append-only). Creates the subject if it does not exist.\n\n**Request body by `type`:**\n- `cookie_banner` – Requires `preferences` object\n- `privacy_policy`, `dpa`, `terms_and_conditions` – Optional `policyId`\n- `marketing_communications`, `age_verification`, `other` – Optional `preferences`",
|
|
3184
3183
|
tags: [
|
|
3185
3184
|
'Subject',
|
|
3186
3185
|
'Consent'
|
|
@@ -3265,7 +3264,7 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
3265
3264
|
if (!value) return;
|
|
3266
3265
|
return (0, schema_.compactDefined)({
|
|
3267
3266
|
allowedActions: (0, schema_.dedupeTrimmedStrings)(value.allowedActions),
|
|
3268
|
-
|
|
3267
|
+
primaryActions: value.primaryActions,
|
|
3269
3268
|
layout: value.layout,
|
|
3270
3269
|
direction: value.direction,
|
|
3271
3270
|
uiProfile: value.uiProfile,
|
|
@@ -3413,9 +3412,7 @@ Use for health checks, load balancer probes, and debugging. Performs a lightweig
|
|
|
3413
3412
|
}));
|
|
3414
3413
|
const publicSpecUrl = `${basePath}${openApiConfig.specPath}`.replace(/\/+/g, '/');
|
|
3415
3414
|
app.get(openApiConfig.docsPath, (0, hono_api_reference_namespaceObject.apiReference)({
|
|
3416
|
-
|
|
3417
|
-
url: publicSpecUrl
|
|
3418
|
-
},
|
|
3415
|
+
url: publicSpecUrl,
|
|
3419
3416
|
pageTitle: `${options.appName || 'c15t API'} Documentation`
|
|
3420
3417
|
}));
|
|
3421
3418
|
}
|