@genn-inc/cluebase-frontend-sdk 0.0.1

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 (140) hide show
  1. package/README.md +222 -0
  2. package/dist/_generated/correlation-attribute-keys.d.ts +2 -0
  3. package/dist/_generated/correlation-attribute-keys.js +33 -0
  4. package/dist/_generated/identity-pii-policy.d.ts +38 -0
  5. package/dist/_generated/identity-pii-policy.js +103 -0
  6. package/dist/_generated/ingest-privacy-tables.d.ts +120 -0
  7. package/dist/_generated/ingest-privacy-tables.js +890 -0
  8. package/dist/_generated/otel-resource-keys.d.ts +21 -0
  9. package/dist/_generated/otel-resource-keys.js +72 -0
  10. package/dist/_generated/otel-span-conversion.d.ts +48 -0
  11. package/dist/_generated/otel-span-conversion.js +69 -0
  12. package/dist/_generated/parameter-snapshot-leaf.d.ts +11 -0
  13. package/dist/_generated/parameter-snapshot-leaf.js +37 -0
  14. package/dist/_generated/sdk-runtime-policy.d.ts +7 -0
  15. package/dist/_generated/sdk-runtime-policy.js +14 -0
  16. package/dist/_generated/usage-governor-tables.d.ts +15 -0
  17. package/dist/_generated/usage-governor-tables.js +44 -0
  18. package/dist/context/browser-storage.d.ts +15 -0
  19. package/dist/context/browser-storage.js +38 -0
  20. package/dist/context/environment.d.ts +37 -0
  21. package/dist/context/environment.js +229 -0
  22. package/dist/context/identity.d.ts +16 -0
  23. package/dist/context/identity.js +139 -0
  24. package/dist/context/organization.d.ts +16 -0
  25. package/dist/context/organization.js +60 -0
  26. package/dist/context/session.d.ts +28 -0
  27. package/dist/context/session.js +130 -0
  28. package/dist/context/tab.d.ts +22 -0
  29. package/dist/context/tab.js +117 -0
  30. package/dist/context/trace.d.ts +76 -0
  31. package/dist/context/trace.js +163 -0
  32. package/dist/exporter/batch.d.ts +94 -0
  33. package/dist/exporter/batch.js +485 -0
  34. package/dist/exporter/browser-outbox-records.d.ts +159 -0
  35. package/dist/exporter/browser-outbox-records.js +341 -0
  36. package/dist/exporter/browser-outbox.d.ts +112 -0
  37. package/dist/exporter/browser-outbox.js +876 -0
  38. package/dist/exporter/client.d.ts +92 -0
  39. package/dist/exporter/client.js +541 -0
  40. package/dist/exporter/delivery-response-contract.d.ts +103 -0
  41. package/dist/exporter/delivery-response-contract.js +147 -0
  42. package/dist/exporter/delivery-response.d.ts +37 -0
  43. package/dist/exporter/delivery-response.js +151 -0
  44. package/dist/exporter/diagnostics.d.ts +42 -0
  45. package/dist/exporter/diagnostics.js +148 -0
  46. package/dist/exporter/event-id.d.ts +10 -0
  47. package/dist/exporter/event-id.js +75 -0
  48. package/dist/exporter/frontend-resource.d.ts +20 -0
  49. package/dist/exporter/frontend-resource.js +52 -0
  50. package/dist/exporter/local-minimization.d.ts +29 -0
  51. package/dist/exporter/local-minimization.js +87 -0
  52. package/dist/exporter/observation-source-event-exporter.d.ts +69 -0
  53. package/dist/exporter/observation-source-event-exporter.js +154 -0
  54. package/dist/exporter/parameter-snapshot.d.ts +14 -0
  55. package/dist/exporter/parameter-snapshot.js +215 -0
  56. package/dist/exporter/path-template.d.ts +1 -0
  57. package/dist/exporter/path-template.js +67 -0
  58. package/dist/exporter/raw-event-to-source-signal.d.ts +12 -0
  59. package/dist/exporter/raw-event-to-source-signal.js +297 -0
  60. package/dist/exporter/retry.d.ts +8 -0
  61. package/dist/exporter/retry.js +8 -0
  62. package/dist/exporter/sanitize.d.ts +30 -0
  63. package/dist/exporter/sanitize.js +177 -0
  64. package/dist/exporter/schema-evidence.d.ts +20 -0
  65. package/dist/exporter/schema-evidence.js +232 -0
  66. package/dist/exporter/source-event.d.ts +99 -0
  67. package/dist/exporter/source-event.js +13 -0
  68. package/dist/exporter/span-to-source-signal.d.ts +8 -0
  69. package/dist/exporter/span-to-source-signal.js +174 -0
  70. package/dist/exporter/text-fingerprint.d.ts +9 -0
  71. package/dist/exporter/text-fingerprint.js +16 -0
  72. package/dist/index.d.ts +25 -0
  73. package/dist/index.js +158 -0
  74. package/dist/instrumentation/action.d.ts +2 -0
  75. package/dist/instrumentation/action.js +171 -0
  76. package/dist/instrumentation/cluebase-authored-attributes.d.ts +4 -0
  77. package/dist/instrumentation/cluebase-authored-attributes.js +32 -0
  78. package/dist/instrumentation/common.d.ts +73 -0
  79. package/dist/instrumentation/common.js +90 -0
  80. package/dist/instrumentation/dom.d.ts +63 -0
  81. package/dist/instrumentation/dom.js +640 -0
  82. package/dist/instrumentation/drag.d.ts +2 -0
  83. package/dist/instrumentation/drag.js +82 -0
  84. package/dist/instrumentation/error.d.ts +2 -0
  85. package/dist/instrumentation/error.js +318 -0
  86. package/dist/instrumentation/form.d.ts +2 -0
  87. package/dist/instrumentation/form.js +132 -0
  88. package/dist/instrumentation/input.d.ts +2 -0
  89. package/dist/instrumentation/input.js +180 -0
  90. package/dist/instrumentation/location.d.ts +11 -0
  91. package/dist/instrumentation/location.js +69 -0
  92. package/dist/instrumentation/naming-evidence.d.ts +20 -0
  93. package/dist/instrumentation/naming-evidence.js +11 -0
  94. package/dist/instrumentation/navigation.d.ts +2 -0
  95. package/dist/instrumentation/navigation.js +144 -0
  96. package/dist/instrumentation/network-request.d.ts +103 -0
  97. package/dist/instrumentation/network-request.js +285 -0
  98. package/dist/instrumentation/network-span-attributes.d.ts +25 -0
  99. package/dist/instrumentation/network-span-attributes.js +153 -0
  100. package/dist/instrumentation/network.d.ts +16 -0
  101. package/dist/instrumentation/network.js +502 -0
  102. package/dist/instrumentation/page.d.ts +2 -0
  103. package/dist/instrumentation/page.js +56 -0
  104. package/dist/instrumentation/performance.d.ts +2 -0
  105. package/dist/instrumentation/performance.js +365 -0
  106. package/dist/integrations/next-router.d.ts +16 -0
  107. package/dist/integrations/next-router.js +18 -0
  108. package/dist/integrations/react-router.d.ts +7 -0
  109. package/dist/integrations/react-router.js +61 -0
  110. package/dist/internal/internal-log.d.ts +23 -0
  111. package/dist/internal/internal-log.js +47 -0
  112. package/dist/internal/metrics.d.ts +10 -0
  113. package/dist/internal/metrics.js +50 -0
  114. package/dist/provider/_version.d.ts +1 -0
  115. package/dist/provider/_version.js +3 -0
  116. package/dist/provider/config.d.ts +12 -0
  117. package/dist/provider/config.js +177 -0
  118. package/dist/provider/constants.d.ts +62 -0
  119. package/dist/provider/constants.js +118 -0
  120. package/dist/provider/contracts.d.ts +51 -0
  121. package/dist/provider/contracts.js +46 -0
  122. package/dist/provider/privacy-policy-store.d.ts +20 -0
  123. package/dist/provider/privacy-policy-store.js +56 -0
  124. package/dist/provider/sampling.d.ts +2 -0
  125. package/dist/provider/sampling.js +17 -0
  126. package/dist/provider/sdk-event-pipeline.d.ts +60 -0
  127. package/dist/provider/sdk-event-pipeline.js +478 -0
  128. package/dist/provider/sdk-input-normalization.d.ts +7 -0
  129. package/dist/provider/sdk-input-normalization.js +113 -0
  130. package/dist/provider/sdk-otel-pipeline.d.ts +14 -0
  131. package/dist/provider/sdk-otel-pipeline.js +148 -0
  132. package/dist/provider/sdk-runtime-surfaces.d.ts +49 -0
  133. package/dist/provider/sdk-runtime-surfaces.js +216 -0
  134. package/dist/provider/sdk.d.ts +2 -0
  135. package/dist/provider/sdk.js +614 -0
  136. package/dist/provider/types.d.ts +323 -0
  137. package/dist/provider/types.js +1 -0
  138. package/dist/provider/usage-governor.d.ts +7 -0
  139. package/dist/provider/usage-governor.js +116 -0
  140. package/package.json +59 -0
@@ -0,0 +1,341 @@
1
+ import { sha256 } from "@noble/hashes/sha256";
2
+ import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils";
3
+ import { canonicalize as canonicalJsonStringify } from "json-canonicalize";
4
+ import { isBrowserSourceSignalEvent, } from "./source-event.js";
5
+ export const UNANCHORED_COLLECTION_GENERATION = "__cluebase_unanchored_generation__";
6
+ export const LEGACY_TOMBSTONE_LIMIT = 10000;
7
+ export const createDraft = (input) => {
8
+ const owned = ownEvent(input.event, input.permit);
9
+ if (!owned)
10
+ return null;
11
+ const event = owned.value();
12
+ const eventId = event.event_id;
13
+ if (typeof eventId !== "string" || eventId.length === 0)
14
+ return null;
15
+ const eventKeyHash = keyHash(eventId);
16
+ return withChecksum({
17
+ storageVersion: 2,
18
+ kind: "draft",
19
+ projectHash: input.projectHash,
20
+ createdAt: input.createdAt,
21
+ recordVerifierSha256: verifyHash(eventId),
22
+ origin: input.origin ?? "v2",
23
+ eventId,
24
+ eventKeyHash,
25
+ event,
26
+ collectionGeneration: input.permit.generation,
27
+ permittedAtStart: input.permit.permittedAtStart,
28
+ });
29
+ };
30
+ export const createLegacyTombstone = (input) => withChecksum({
31
+ storageVersion: 2,
32
+ kind: "legacy_tombstone",
33
+ projectHash: input.projectHash,
34
+ createdAt: nowIso(),
35
+ recordVerifierSha256: input.verifier,
36
+ eventKeyHash: input.eventKeyHash,
37
+ importedAt: nowIso(),
38
+ });
39
+ export const createConsentRecord = (input) => withChecksum({
40
+ storageVersion: 2,
41
+ kind: "consent",
42
+ projectHash: input.projectHash,
43
+ createdAt: nowIso(),
44
+ updatedAt: nowIso(),
45
+ recordVerifierSha256: null,
46
+ state: input.state,
47
+ collectionGeneration: input.collectionGeneration,
48
+ legacyImportBlocked: input.legacyImportBlocked,
49
+ });
50
+ export const createPending = (input) => {
51
+ const events = input.drafts.map((draft) => ({
52
+ eventId: draft.eventId,
53
+ eventKeyHash: draft.eventKeyHash,
54
+ recordVerifierSha256: draft.recordVerifierSha256 ?? verifyHash(draft.eventId),
55
+ event: draft.event,
56
+ permittedAtStart: draft.permittedAtStart,
57
+ }));
58
+ return withChecksum({
59
+ storageVersion: 2,
60
+ kind: "pending",
61
+ projectHash: input.projectHash,
62
+ createdAt: nowIso(),
63
+ recordVerifierSha256: verifyHash(input.metadata.batch_id),
64
+ batchId: input.metadata.batch_id,
65
+ idempotencyKey: input.metadata.idempotency_key,
66
+ sentAt: input.metadata.sent_at,
67
+ collectionGeneration: input.drafts[0]?.collectionGeneration ?? "",
68
+ events,
69
+ eventKeyHashes: events.map((event) => event.eventKeyHash),
70
+ lifetimeAttemptTotal: 0,
71
+ ordinal: input.ordinal,
72
+ });
73
+ };
74
+ export const toPendingBatch = (record, recordKey, events, metadata, planOrdinal) => {
75
+ const owned = events
76
+ .map((event) => ownEvent(event.event, {
77
+ generation: record.collectionGeneration,
78
+ permittedAtStart: event.permittedAtStart,
79
+ captureOrdinal: 0,
80
+ }))
81
+ .filter(isOwnedEvent);
82
+ return Object.freeze({
83
+ events: Object.freeze(owned),
84
+ metadata: Object.freeze({ ...metadata }),
85
+ generation: record.collectionGeneration,
86
+ ordinal: record.ordinal,
87
+ diagnosticCanonicalBytes: canonicalJsonStringify({
88
+ sourceType: "frontend_sdk",
89
+ sourceSchemaVersion: "1",
90
+ batchId: metadata.batch_id,
91
+ idempotencyKey: metadata.idempotency_key,
92
+ sentAt: metadata.sent_at,
93
+ events: owned.map((event) => event.value()),
94
+ }),
95
+ recordKey,
96
+ ownerBatchId: record.batchId,
97
+ planOrdinal,
98
+ });
99
+ };
100
+ export const toHeadBatch = (record, recordKey) => {
101
+ if (record.kind === "pending") {
102
+ return toPendingBatch(record, recordKey, record.events, {
103
+ batch_id: record.batchId,
104
+ idempotency_key: record.idempotencyKey,
105
+ sent_at: record.sentAt,
106
+ }, null);
107
+ }
108
+ const child = record.children[record.nextOrdinal];
109
+ if (!child)
110
+ return null;
111
+ return toPendingBatch(record, recordKey, record.events.slice(child.start, child.end), child.metadata, record.nextOrdinal);
112
+ };
113
+ export const splitPendingRecord = (record, createMetadata) => {
114
+ const child = record.kind === "pending"
115
+ ? {
116
+ start: 0,
117
+ end: record.events.length,
118
+ metadata: {
119
+ batch_id: record.batchId,
120
+ idempotency_key: record.idempotencyKey,
121
+ sent_at: record.sentAt,
122
+ },
123
+ }
124
+ : record.children[record.nextOrdinal];
125
+ if (!child || child.end - child.start < 2)
126
+ return null;
127
+ const boundary = child.start + Math.ceil((child.end - child.start) / 2);
128
+ const replacements = [
129
+ { start: child.start, end: boundary, metadata: createMetadata() },
130
+ { start: boundary, end: child.end, metadata: createMetadata() },
131
+ ];
132
+ return withChecksum({
133
+ ...withoutChecksum(record),
134
+ kind: "split_plan",
135
+ children: record.kind === "pending"
136
+ ? replacements
137
+ : [
138
+ ...record.children.slice(0, record.nextOrdinal),
139
+ ...replacements,
140
+ ...record.children.slice(record.nextOrdinal + 1),
141
+ ],
142
+ nextOrdinal: record.kind === "pending" ? 0 : record.nextOrdinal,
143
+ });
144
+ };
145
+ export const largestFittingPrefix = (drafts, maxBytes, metadata, measure) => {
146
+ let low = 1;
147
+ let high = drafts.length;
148
+ let largest = 0;
149
+ while (low <= high) {
150
+ const count = Math.floor((low + high) / 2);
151
+ if (measure(drafts.slice(0, count).map((draft) => draft.event), metadata) <= maxBytes) {
152
+ largest = count;
153
+ low = count + 1;
154
+ }
155
+ else {
156
+ high = count - 1;
157
+ }
158
+ }
159
+ return largest;
160
+ };
161
+ export const ownEvent = (event, permit) => {
162
+ try {
163
+ const json = JSON.stringify(event);
164
+ const parsed = JSON.parse(json);
165
+ if (!isBrowserSourceSignalEvent(parsed))
166
+ return null;
167
+ return Object.freeze({
168
+ byteLength: new TextEncoder().encode(json).byteLength,
169
+ permit: Object.freeze({ ...permit }),
170
+ diagnosticCanonicalBytes: canonicalJsonStringify(parsed),
171
+ value: () => JSON.parse(json),
172
+ });
173
+ }
174
+ catch {
175
+ return null;
176
+ }
177
+ };
178
+ export const isOwnedEvent = (value) => value !== null;
179
+ export const recordBatchId = (batch) => batch.ownerBatchId;
180
+ export const withChecksum = (record) => ({
181
+ ...record,
182
+ checksumSha256: sha256Hex(canonicalJsonStringify(record)),
183
+ });
184
+ export const withoutChecksum = (record) => {
185
+ const { checksumSha256: _checksumSha256, ...unsigned } = record;
186
+ return unsigned;
187
+ };
188
+ export const parseRecord = (raw, projectHash) => {
189
+ try {
190
+ const value = JSON.parse(raw);
191
+ if (!isRecord(value) || value.storageVersion !== 2 || value.projectHash !== projectHash)
192
+ return null;
193
+ const checksumSha256 = value.checksumSha256;
194
+ if (typeof checksumSha256 !== "string")
195
+ return null;
196
+ const { checksumSha256: _checksum, ...unsigned } = value;
197
+ if (sha256Hex(canonicalJsonStringify(unsigned)) !== checksumSha256)
198
+ return null;
199
+ return isValidRecord(value) ? value : null;
200
+ }
201
+ catch {
202
+ return null;
203
+ }
204
+ };
205
+ const isValidRecord = (value) => {
206
+ const base = typeof value.createdAt === "string" &&
207
+ (typeof value.recordVerifierSha256 === "string" || value.recordVerifierSha256 === null);
208
+ if (!base)
209
+ return false;
210
+ if (value.kind === "consent") {
211
+ return ((value.state === "granted" || value.state === "denied" || value.state === "unknown") &&
212
+ typeof value.collectionGeneration === "string" &&
213
+ typeof value.legacyImportBlocked === "boolean" &&
214
+ typeof value.updatedAt === "string" &&
215
+ value.recordVerifierSha256 === null);
216
+ }
217
+ if (value.kind === "draft") {
218
+ return ((value.origin === "v2" || value.origin === "legacy_v1") &&
219
+ typeof value.eventId === "string" &&
220
+ typeof value.eventKeyHash === "string" &&
221
+ value.eventKeyHash === keyHash(value.eventId) &&
222
+ value.recordVerifierSha256 === verifyHash(value.eventId) &&
223
+ typeof value.collectionGeneration === "string" &&
224
+ typeof value.permittedAtStart === "boolean" &&
225
+ isBrowserSourceSignalEvent(value.event));
226
+ }
227
+ if (value.kind === "legacy_tombstone") {
228
+ return typeof value.eventKeyHash === "string" && typeof value.importedAt === "string";
229
+ }
230
+ if (value.kind === "pending" || value.kind === "split_plan") {
231
+ if (typeof value.batchId !== "string" ||
232
+ typeof value.idempotencyKey !== "string" ||
233
+ typeof value.sentAt !== "string" ||
234
+ typeof value.collectionGeneration !== "string" ||
235
+ !Array.isArray(value.events) ||
236
+ !Array.isArray(value.eventKeyHashes) ||
237
+ !Number.isInteger(value.lifetimeAttemptTotal) ||
238
+ !Number.isInteger(value.ordinal))
239
+ return false;
240
+ const events = value.events;
241
+ const eventKeyHashes = value.eventKeyHashes;
242
+ if (value.recordVerifierSha256 !== verifyHash(value.batchId) ||
243
+ eventKeyHashes.length !== events.length ||
244
+ !events.every(isStoredEvent) ||
245
+ !events.every((event, index) => eventKeyHashes[index] === event.eventKeyHash))
246
+ return false;
247
+ if (value.kind === "pending")
248
+ return true;
249
+ const children = value.children;
250
+ return (Array.isArray(children) &&
251
+ children.length >= 2 &&
252
+ children.every((child) => isPlanSide(child, events.length)) &&
253
+ children[0]?.start === 0 &&
254
+ children.every((child, index) => index === 0 || children[index - 1]?.end === child.start) &&
255
+ children[children.length - 1]?.end === events.length &&
256
+ Number.isInteger(value.nextOrdinal) &&
257
+ typeof value.nextOrdinal === "number" &&
258
+ value.nextOrdinal >= 0 &&
259
+ value.nextOrdinal < children.length);
260
+ }
261
+ return false;
262
+ };
263
+ const isStoredEvent = (value) => isRecord(value) &&
264
+ typeof value.eventId === "string" &&
265
+ typeof value.eventKeyHash === "string" &&
266
+ value.eventKeyHash === keyHash(value.eventId) &&
267
+ typeof value.recordVerifierSha256 === "string" &&
268
+ value.recordVerifierSha256 === verifyHash(value.eventId) &&
269
+ typeof value.permittedAtStart === "boolean" &&
270
+ isBrowserSourceSignalEvent(value.event);
271
+ const isPlanSide = (value, eventCount) => isRecord(value) &&
272
+ typeof value.start === "number" &&
273
+ typeof value.end === "number" &&
274
+ Number.isInteger(value.start) &&
275
+ Number.isInteger(value.end) &&
276
+ value.start >= 0 &&
277
+ value.end > value.start &&
278
+ value.end <= eventCount &&
279
+ isMetadata(value.metadata);
280
+ const isMetadata = (value) => isRecord(value) &&
281
+ typeof value.batch_id === "string" &&
282
+ typeof value.idempotency_key === "string" &&
283
+ typeof value.sent_at === "string";
284
+ export const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
285
+ export const sha256Hex = (value) => bytesToHex(sha256(utf8ToBytes(value)));
286
+ export const keyHash = (id) => sha256Hex(`cluebase:outbox-key:v2\0${id}`);
287
+ export const verifyHash = (id) => sha256Hex(`cluebase:outbox-verify:v2\0${id}`);
288
+ export const nowIso = () => new Date().toISOString();
289
+ export const consentRecordKey = (prefix) => `${prefix}consent`;
290
+ export const draftRecordKey = (prefix, eventKeyHash) => `${prefix}draft:${eventKeyHash}`;
291
+ export const pendingRecordKey = (prefix, batchId) => `${prefix}pending:${keyHash(batchId)}`;
292
+ export const tombstoneRecordKey = (prefix, eventKeyHash) => `${prefix}legacy-tombstone:${eventKeyHash}`;
293
+ export const browserEventsByteLength = (events) => events.reduce((total, event) => total + new TextEncoder().encode(JSON.stringify(event)).byteLength, 0);
294
+ export const outboxEventCount = (drafts, pending) => drafts.length + pending.reduce((count, record) => count + record.events.length, 0);
295
+ export const hasLegacyTombstone = (draft, tombstones) => tombstones.some((record) => record.eventKeyHash === draft.eventKeyHash &&
296
+ record.recordVerifierSha256 === draft.recordVerifierSha256);
297
+ export const createGeneration = () => typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
298
+ ? crypto.randomUUID()
299
+ : `${Date.now()}-${Math.random()}`;
300
+ export const readStorage = () => {
301
+ try {
302
+ return typeof localStorage === "undefined" ? null : localStorage;
303
+ }
304
+ catch {
305
+ return null;
306
+ }
307
+ };
308
+ export const readLocks = () => {
309
+ const navigatorValue = globalThis.navigator;
310
+ return navigatorValue?.locks ?? null;
311
+ };
312
+ export const createConsentChannel = (projectHash, onDenied) => {
313
+ if (typeof BroadcastChannel === "undefined")
314
+ return null;
315
+ try {
316
+ const channel = new BroadcastChannel(`cluebase:source-event-consent:v2:${projectHash}`);
317
+ channel.addEventListener("message", (event) => {
318
+ const data = event.data;
319
+ if (isRecord(data) &&
320
+ data.type === "denied" &&
321
+ typeof data.generation === "string" &&
322
+ data.generation.length > 0) {
323
+ onDenied(data.generation);
324
+ }
325
+ });
326
+ return channel;
327
+ }
328
+ catch {
329
+ return null;
330
+ }
331
+ };
332
+ export const addStorageListener = (key, onChanged) => {
333
+ if (typeof globalThis.addEventListener !== "function")
334
+ return () => undefined;
335
+ const listener = (event) => {
336
+ if (event.key === key)
337
+ onChanged();
338
+ };
339
+ globalThis.addEventListener("storage", listener);
340
+ return () => globalThis.removeEventListener("storage", listener);
341
+ };
@@ -0,0 +1,112 @@
1
+ import type { InternalMetricsStore } from "../internal/metrics.js";
2
+ import type { CluebaseConsentState } from "../provider/types.js";
3
+ import type { BatchEnvelopeMetadata } from "./client.js";
4
+ import { DiagnosticStore } from "./diagnostics.js";
5
+ import type { BrowserSourceEvent } from "./source-event.js";
6
+ import { type CollectionPermit, type PendingBrowserBatch, type StorageLike } from "./browser-outbox-records.js";
7
+ export type { CollectionPermit, OwnedBrowserEvent, PendingBrowserBatch } from "./browser-outbox-records.js";
8
+ export type ConsentTransition = {
9
+ readonly state: CluebaseConsentState;
10
+ readonly generation: string;
11
+ readonly expectedGeneration: string | null;
12
+ readonly recoveryExpectedRaw?: string | null | false;
13
+ readonly legacyImportBlocked: boolean;
14
+ readonly purge: boolean;
15
+ };
16
+ export declare class BrowserOutbox {
17
+ private readonly projectHash;
18
+ private readonly prefix;
19
+ private readonly consentKey;
20
+ private readonly legacyKey;
21
+ private readonly lockName;
22
+ private readonly storage;
23
+ private readonly durableOutboxSupported;
24
+ private readonly maxBytes;
25
+ private readonly maxEvents;
26
+ private readonly metrics;
27
+ private readonly diagnostics;
28
+ private drafts;
29
+ private pending;
30
+ private tombstones;
31
+ private nextOrdinal;
32
+ private consent;
33
+ private generation;
34
+ private nextPermitOrdinal;
35
+ private legacyImportBlocked;
36
+ private consentAnchorEstablished;
37
+ private initialDenialPending;
38
+ private memoryOnly;
39
+ private durableWarningRecorded;
40
+ private deliveryLockHeld;
41
+ private purgePending;
42
+ private consentStateUnavailable;
43
+ private readonly onConsentRevoked;
44
+ private readonly consentChannel;
45
+ private readonly removeConsentStorageListener;
46
+ private readonly removeLegacyStorageListener;
47
+ constructor(options: {
48
+ readonly projectKey: string;
49
+ readonly initialConsent: CluebaseConsentState;
50
+ readonly maxBytes: number;
51
+ readonly maxEvents: number;
52
+ readonly metrics?: InternalMetricsStore;
53
+ readonly diagnostics?: DiagnosticStore;
54
+ readonly storage?: StorageLike | null;
55
+ readonly onConsentRevoked?: () => void;
56
+ });
57
+ currentConsent(): CluebaseConsentState;
58
+ capturePermit(): CollectionPermit;
59
+ permits(permit: CollectionPermit): boolean;
60
+ setConsent(next: CluebaseConsentState): ConsentTransition;
61
+ commitConsentTransition(transition: ConsentTransition): void;
62
+ private persistCommittedConsent;
63
+ addDraft(event: BrowserSourceEvent, permit?: CollectionPermit): boolean;
64
+ estimatedDraftBytes(measure: (events: readonly BrowserSourceEvent[], metadata: BatchEnvelopeMetadata) => number, metadata: BatchEnvelopeMetadata): number;
65
+ prepareFence(input: {
66
+ readonly maxPayloadBytes: number;
67
+ readonly createMetadata: () => BatchEnvelopeMetadata;
68
+ readonly measure: (events: readonly BrowserSourceEvent[], metadata: BatchEnvelopeMetadata) => number;
69
+ }): {
70
+ readonly targetOrdinal: number;
71
+ readonly oversized: number;
72
+ };
73
+ headThrough(targetOrdinal: number): PendingBrowserBatch | null;
74
+ removeHead(expected: PendingBrowserBatch): boolean;
75
+ retainHead(expected: PendingBrowserBatch): boolean;
76
+ splitHead(expected: PendingBrowserBatch, createMetadata: () => BatchEnvelopeMetadata): boolean;
77
+ clear(): boolean;
78
+ close(): void;
79
+ pendingEventCount(): number;
80
+ pendingBytes(): number;
81
+ withDeliveryLock<T>(operation: () => Promise<T>, options?: {
82
+ readonly restore?: boolean;
83
+ }): Promise<T>;
84
+ private permitsBatch;
85
+ private resolvePermit;
86
+ private initializeConsentForDelivery;
87
+ private enforceCapacity;
88
+ private purgeAll;
89
+ clearMemory(): void;
90
+ private restore;
91
+ private restoreOutbox;
92
+ private readConsent;
93
+ private peekConsentRaw;
94
+ private restoreConsentFromStorage;
95
+ private reconcileRemotePermittedConsent;
96
+ private adoptConsentRecord;
97
+ private repairDeniedConsentState;
98
+ private importLegacy;
99
+ private readLegacyEvents;
100
+ private applyRemoteDenial;
101
+ private persistConsent;
102
+ private writeRecord;
103
+ private removeRecord;
104
+ private removeDraft;
105
+ private removeClaimedDraftRecords;
106
+ private readRecord;
107
+ private failClosedConsentState;
108
+ private storageKeys;
109
+ private rawStorageKeys;
110
+ private removeRawRecord;
111
+ private warnDurableUnavailable;
112
+ }