@peax/consent-core 0.6.0
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/LICENSE +201 -0
- package/README.md +207 -0
- package/dist/ConsentEnforcementError-Bn_ayWJI.js +16 -0
- package/dist/assertStorageIdentifier-BQuj-9bp.js +7 -0
- package/dist/createConsentIframe-Bw-cl--m.js +93 -0
- package/dist/createConsentRequestScope-D7U8uK6m.js +58 -0
- package/dist/createConsentScript-C_4ecSTX.js +102 -0
- package/dist/createDomGuard-CuIEC0HP.js +101 -0
- package/dist/enforcement/axios.d.ts +222 -0
- package/dist/enforcement/axios.js +92 -0
- package/dist/enforcement/fetch.d.ts +222 -0
- package/dist/enforcement/fetch.js +40 -0
- package/dist/enforcement/iframe.d.ts +245 -0
- package/dist/enforcement/iframe.js +2 -0
- package/dist/enforcement/integration.d.ts +230 -0
- package/dist/enforcement/integration.js +181 -0
- package/dist/enforcement/markup.d.ts +214 -0
- package/dist/enforcement/markup.js +300 -0
- package/dist/enforcement/posthog.d.ts +68 -0
- package/dist/enforcement/posthog.js +96 -0
- package/dist/enforcement/request-rules.d.ts +248 -0
- package/dist/enforcement/request-rules.js +434 -0
- package/dist/enforcement/script.d.ts +240 -0
- package/dist/enforcement/script.js +2 -0
- package/dist/index.d.ts +258 -0
- package/dist/index.js +445 -0
- package/dist/storage/localforage.d.ts +23 -0
- package/dist/storage/localforage.js +26 -0
- package/dist/storage/sync.d.ts +278 -0
- package/dist/storage/sync.js +370 -0
- package/dist/storage.d.ts +77 -0
- package/dist/storage.js +207 -0
- package/dist/validate-D16G7mdG.js +15 -0
- package/package.json +128 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { t as requireConsent } from "../validate-D16G7mdG.js";
|
|
2
|
+
import { t as createConsentScript } from "../createConsentScript-C_4ecSTX.js";
|
|
3
|
+
import { t as createConsentIframe } from "../createConsentIframe-Bw-cl--m.js";
|
|
4
|
+
//#region src/enforcement/markup/createConsentMarkupGuard.ts
|
|
5
|
+
var selector = "script[data-peax-use-id],script[data-peax-src],iframe[data-peax-use-id],iframe[data-peax-src]";
|
|
6
|
+
/**
|
|
7
|
+
* Every attribute the guard observes, in one table. The observer filter, the change signature and
|
|
8
|
+
* the option readers all derive from it, and `read` accepts only these keys, so an attribute cannot
|
|
9
|
+
* be read without also being watched and compared.
|
|
10
|
+
*/
|
|
11
|
+
var attributes = {
|
|
12
|
+
useId: "data-peax-use-id",
|
|
13
|
+
markerSrc: "data-peax-src",
|
|
14
|
+
scriptType: "data-peax-script-type",
|
|
15
|
+
async: "data-peax-async",
|
|
16
|
+
liveSrc: "src",
|
|
17
|
+
srcdoc: "srcdoc",
|
|
18
|
+
textType: "type",
|
|
19
|
+
nonce: "nonce",
|
|
20
|
+
integrity: "integrity",
|
|
21
|
+
crossOrigin: "crossorigin",
|
|
22
|
+
referrerPolicy: "referrerpolicy",
|
|
23
|
+
title: "title",
|
|
24
|
+
sandbox: "sandbox",
|
|
25
|
+
allow: "allow",
|
|
26
|
+
loading: "loading",
|
|
27
|
+
width: "width",
|
|
28
|
+
height: "height"
|
|
29
|
+
};
|
|
30
|
+
var attributeKeys = Object.keys(attributes);
|
|
31
|
+
var attributeNames = Object.values(attributes);
|
|
32
|
+
function isTemplate(value) {
|
|
33
|
+
return value.localName === "script" || value.localName === "iframe";
|
|
34
|
+
}
|
|
35
|
+
/** Reads one observed attribute. Absent attributes are undefined so options and signatures agree. */
|
|
36
|
+
function read(template, key) {
|
|
37
|
+
return template.getAttribute(attributes[key]) ?? void 0;
|
|
38
|
+
}
|
|
39
|
+
/** Framework-neutral, opt-in management of inert marked nodes only. */
|
|
40
|
+
function createConsentMarkupGuard({ consent, root, onIssue }) {
|
|
41
|
+
requireConsent(consent);
|
|
42
|
+
if (!root || root.nodeType !== 9 && root.nodeType !== 1) throw new TypeError("Expected a document or element root.");
|
|
43
|
+
if (onIssue !== void 0 && typeof onIssue !== "function") throw new TypeError("Expected an issue callback.");
|
|
44
|
+
const document = root.nodeType === 9 ? root : root.ownerDocument;
|
|
45
|
+
const managed = /* @__PURE__ */ new Map();
|
|
46
|
+
const invalid = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
const insertedScripts = /* @__PURE__ */ new WeakSet();
|
|
48
|
+
const reloadRequired = /* @__PURE__ */ new Set();
|
|
49
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
50
|
+
let started = false;
|
|
51
|
+
let disposed = false;
|
|
52
|
+
let observer;
|
|
53
|
+
let unsubscribe;
|
|
54
|
+
function report(template, reason, error) {
|
|
55
|
+
onIssue?.(Object.freeze({
|
|
56
|
+
element: template,
|
|
57
|
+
reason,
|
|
58
|
+
error
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
function reportInvalidMarker(template, currentSignature, error) {
|
|
62
|
+
if (invalid.get(template) === currentSignature) return;
|
|
63
|
+
invalid.set(template, currentSignature);
|
|
64
|
+
report(template, "invalid-marker", error);
|
|
65
|
+
}
|
|
66
|
+
function attempt(action, failures) {
|
|
67
|
+
try {
|
|
68
|
+
action();
|
|
69
|
+
} catch (error) {
|
|
70
|
+
failures.push(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function finish(failures) {
|
|
74
|
+
if (failures.length) throw new AggregateError(failures, "Markup lifecycle failed after cleanup.");
|
|
75
|
+
}
|
|
76
|
+
function requireReload(useId, failures) {
|
|
77
|
+
if (reloadRequired.has(useId)) return;
|
|
78
|
+
reloadRequired.add(useId);
|
|
79
|
+
for (const listener of [...listeners]) if (listeners.has(listener)) attempt(listener, failures);
|
|
80
|
+
}
|
|
81
|
+
function drop(entry, failures) {
|
|
82
|
+
managed.delete(entry.template);
|
|
83
|
+
if (entry.kind === "script" && entry.inserted) requireReload(entry.useId, failures);
|
|
84
|
+
attempt(() => entry.handle?.remove(), failures);
|
|
85
|
+
attempt(() => entry.guard.dispose(), failures);
|
|
86
|
+
}
|
|
87
|
+
function readMarker(template) {
|
|
88
|
+
const useId = read(template, "useId");
|
|
89
|
+
const src = read(template, "markerSrc");
|
|
90
|
+
if (!useId?.trim() || !src?.trim() || read(template, "liveSrc") !== void 0 || read(template, "srcdoc") !== void 0) throw new TypeError("Marked resource requires a use ID and data-peax-src, without a live src or srcdoc.");
|
|
91
|
+
if (template.localName === "script" && (read(template, "textType") !== "text/plain" || template.textContent?.trim())) throw new TypeError("Marked external scripts require type=\"text/plain\" and no inline code.");
|
|
92
|
+
return {
|
|
93
|
+
useId,
|
|
94
|
+
src,
|
|
95
|
+
kind: template.localName
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function signature(template) {
|
|
99
|
+
return JSON.stringify([...attributeKeys.map((key) => read(template, key) ?? null), template.localName === "script" ? template.textContent : null]);
|
|
100
|
+
}
|
|
101
|
+
function mount(entry) {
|
|
102
|
+
if (entry.handle || entry.kind === "script" && (entry.inserted || insertedScripts.has(entry.template) || reloadRequired.has(entry.useId))) return;
|
|
103
|
+
if (!consent.evaluate(entry.useId).allowed) return;
|
|
104
|
+
const parent = entry.template.parentElement;
|
|
105
|
+
if (!parent?.isConnected) return;
|
|
106
|
+
try {
|
|
107
|
+
if (entry.kind === "script") {
|
|
108
|
+
const template = entry.template;
|
|
109
|
+
const asyncValue = read(template, "async");
|
|
110
|
+
if (asyncValue !== void 0 && asyncValue !== "true" && asyncValue !== "false") throw new TypeError("Invalid data-peax-async value.");
|
|
111
|
+
const { nonce, integrity, crossOrigin, referrerPolicy } = {
|
|
112
|
+
nonce: read(template, "nonce"),
|
|
113
|
+
integrity: read(template, "integrity"),
|
|
114
|
+
crossOrigin: read(template, "crossOrigin"),
|
|
115
|
+
referrerPolicy: read(template, "referrerPolicy")
|
|
116
|
+
};
|
|
117
|
+
const options = {
|
|
118
|
+
src: entry.src,
|
|
119
|
+
parent,
|
|
120
|
+
type: read(template, "scriptType") ?? "classic",
|
|
121
|
+
async: asyncValue === void 0 ? true : asyncValue === "true",
|
|
122
|
+
...nonce === void 0 ? {} : { nonce },
|
|
123
|
+
...integrity === void 0 ? {} : { integrity },
|
|
124
|
+
...crossOrigin === void 0 ? {} : { crossOrigin },
|
|
125
|
+
...referrerPolicy === void 0 ? {} : { referrerPolicy }
|
|
126
|
+
};
|
|
127
|
+
const handle = entry.guard.load(options);
|
|
128
|
+
entry.handle = handle;
|
|
129
|
+
entry.inserted = true;
|
|
130
|
+
insertedScripts.add(template);
|
|
131
|
+
handle.ready.catch((error) => {
|
|
132
|
+
if (managed.get(entry.template) !== entry) return;
|
|
133
|
+
if (error?.reason === "load-error") report(entry.template, "load-error", error);
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
const template = entry.template;
|
|
137
|
+
const { title, sandbox, allow, referrerPolicy, loading, width, height } = {
|
|
138
|
+
title: read(template, "title") ?? "",
|
|
139
|
+
sandbox: read(template, "sandbox"),
|
|
140
|
+
allow: read(template, "allow"),
|
|
141
|
+
referrerPolicy: read(template, "referrerPolicy"),
|
|
142
|
+
loading: read(template, "loading"),
|
|
143
|
+
width: read(template, "width"),
|
|
144
|
+
height: read(template, "height")
|
|
145
|
+
};
|
|
146
|
+
const options = {
|
|
147
|
+
parent,
|
|
148
|
+
src: entry.src,
|
|
149
|
+
title,
|
|
150
|
+
...sandbox === void 0 ? {} : { sandbox },
|
|
151
|
+
...allow === void 0 ? {} : { allow },
|
|
152
|
+
...referrerPolicy === void 0 ? {} : { referrerPolicy },
|
|
153
|
+
...loading === void 0 ? {} : { loading },
|
|
154
|
+
...width === void 0 ? {} : { width },
|
|
155
|
+
...height === void 0 ? {} : { height }
|
|
156
|
+
};
|
|
157
|
+
entry.handle = entry.guard.mount(options);
|
|
158
|
+
entry.inserted = true;
|
|
159
|
+
}
|
|
160
|
+
invalid.delete(entry.template);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
reportInvalidMarker(entry.template, signature(entry.template), error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function reconcile(entry, failures) {
|
|
166
|
+
if (!consent.evaluate(entry.useId).allowed) {
|
|
167
|
+
if (entry.handle) {
|
|
168
|
+
if (entry.kind === "script") requireReload(entry.useId, failures);
|
|
169
|
+
const handle = entry.handle;
|
|
170
|
+
entry.handle = void 0;
|
|
171
|
+
attempt(() => handle.remove(), failures);
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
mount(entry);
|
|
176
|
+
}
|
|
177
|
+
function observeTemplate(template, failures) {
|
|
178
|
+
if (!template.isConnected || !root.contains(template)) return;
|
|
179
|
+
const currentSignature = signature(template);
|
|
180
|
+
let marker;
|
|
181
|
+
try {
|
|
182
|
+
marker = readMarker(template);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
const previous = managed.get(template);
|
|
185
|
+
if (previous) drop(previous, failures);
|
|
186
|
+
reportInvalidMarker(template, currentSignature, error);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (invalid.get(template) !== currentSignature) invalid.delete(template);
|
|
190
|
+
const previous = managed.get(template);
|
|
191
|
+
if (previous && previous.signature === currentSignature) {
|
|
192
|
+
reconcile(previous, failures);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (previous) drop(previous, failures);
|
|
196
|
+
const guard = marker.kind === "script" ? createConsentScript({
|
|
197
|
+
consent,
|
|
198
|
+
useId: marker.useId
|
|
199
|
+
}) : createConsentIframe({
|
|
200
|
+
consent,
|
|
201
|
+
useId: marker.useId
|
|
202
|
+
});
|
|
203
|
+
const entry = {
|
|
204
|
+
template,
|
|
205
|
+
...marker,
|
|
206
|
+
signature: currentSignature,
|
|
207
|
+
guard,
|
|
208
|
+
inserted: false,
|
|
209
|
+
handle: void 0
|
|
210
|
+
};
|
|
211
|
+
managed.set(template, entry);
|
|
212
|
+
reconcile(entry, failures);
|
|
213
|
+
}
|
|
214
|
+
function scanNode(node, failures) {
|
|
215
|
+
if (node.nodeType !== 1) return;
|
|
216
|
+
const element = node;
|
|
217
|
+
if (isTemplate(element) && element.matches(selector)) observeTemplate(element, failures);
|
|
218
|
+
for (const candidate of element.querySelectorAll(selector)) if (isTemplate(candidate)) observeTemplate(candidate, failures);
|
|
219
|
+
}
|
|
220
|
+
function scan(failures) {
|
|
221
|
+
if (root.nodeType === 1) scanNode(root, failures);
|
|
222
|
+
else for (const candidate of root.querySelectorAll(selector)) if (isTemplate(candidate)) observeTemplate(candidate, failures);
|
|
223
|
+
}
|
|
224
|
+
function pruneRemoved(failures) {
|
|
225
|
+
for (const entry of [...managed.values()]) if (!entry.template.isConnected || !root.contains(entry.template)) drop(entry, failures);
|
|
226
|
+
}
|
|
227
|
+
return Object.freeze({
|
|
228
|
+
start() {
|
|
229
|
+
if (disposed) throw new Error("Markup guard is disposed.");
|
|
230
|
+
if (started) return;
|
|
231
|
+
const Observer = document.defaultView?.MutationObserver;
|
|
232
|
+
if (!Observer) throw new TypeError("Markup guard requires a browser MutationObserver.");
|
|
233
|
+
started = true;
|
|
234
|
+
try {
|
|
235
|
+
unsubscribe = consent.subscribe(() => {
|
|
236
|
+
const failures = [];
|
|
237
|
+
for (const entry of [...managed.values()]) attempt(() => reconcile(entry, failures), failures);
|
|
238
|
+
finish(failures);
|
|
239
|
+
});
|
|
240
|
+
observer = new Observer((records) => {
|
|
241
|
+
const failures = [];
|
|
242
|
+
const changed = /* @__PURE__ */ new Set();
|
|
243
|
+
let removed = false;
|
|
244
|
+
for (const record of records) if (record.type === "childList") {
|
|
245
|
+
for (const node of record.addedNodes) attempt(() => scanNode(node, failures), failures);
|
|
246
|
+
if (record.removedNodes.length) removed = true;
|
|
247
|
+
const target = record.target;
|
|
248
|
+
if (target.nodeType === 1 && isTemplate(target) && managed.has(target)) changed.add(target);
|
|
249
|
+
} else {
|
|
250
|
+
const target = record.type === "characterData" ? record.target.parentElement : record.target;
|
|
251
|
+
if (target?.nodeType === 1 && isTemplate(target) && (target.matches(selector) || managed.has(target))) changed.add(target);
|
|
252
|
+
}
|
|
253
|
+
for (const template of changed) attempt(() => observeTemplate(template, failures), failures);
|
|
254
|
+
if (removed) pruneRemoved(failures);
|
|
255
|
+
finish(failures);
|
|
256
|
+
});
|
|
257
|
+
observer.observe(root, {
|
|
258
|
+
subtree: true,
|
|
259
|
+
childList: true,
|
|
260
|
+
attributes: true,
|
|
261
|
+
characterData: true,
|
|
262
|
+
attributeFilter: attributeNames
|
|
263
|
+
});
|
|
264
|
+
const failures = [];
|
|
265
|
+
scan(failures);
|
|
266
|
+
finish(failures);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
const failures = [];
|
|
269
|
+
attempt(() => observer?.disconnect(), failures);
|
|
270
|
+
observer = void 0;
|
|
271
|
+
attempt(() => unsubscribe?.(), failures);
|
|
272
|
+
unsubscribe = void 0;
|
|
273
|
+
for (const entry of [...managed.values()]) drop(entry, failures);
|
|
274
|
+
started = false;
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
getReloadRequiredUseIds: () => Object.freeze([...reloadRequired]),
|
|
279
|
+
subscribe(listener) {
|
|
280
|
+
if (typeof listener !== "function") throw new TypeError("Expected a reload listener.");
|
|
281
|
+
if (disposed) return () => {};
|
|
282
|
+
listeners.add(listener);
|
|
283
|
+
return () => {
|
|
284
|
+
listeners.delete(listener);
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
dispose() {
|
|
288
|
+
if (disposed) return;
|
|
289
|
+
disposed = true;
|
|
290
|
+
const failures = [];
|
|
291
|
+
attempt(() => observer?.disconnect(), failures);
|
|
292
|
+
attempt(() => unsubscribe?.(), failures);
|
|
293
|
+
for (const entry of [...managed.values()]) drop(entry, failures);
|
|
294
|
+
listeners.clear();
|
|
295
|
+
finish(failures);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
export { createConsentMarkupGuard };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
declare type Common = Readonly<{
|
|
2
|
+
id: string;
|
|
3
|
+
useId: string;
|
|
4
|
+
}>;
|
|
5
|
+
|
|
6
|
+
declare type ConsentIntegrationActivation = Readonly<{
|
|
7
|
+
/** Called when consent stops allowing this use or the manager is disposed. */
|
|
8
|
+
deactivate: (reason: IntegrationDeactivationReason) => void | Promise<void>;
|
|
9
|
+
/** Executed code cannot be undone; a fresh page is required after deactivation. */
|
|
10
|
+
reloadOnDeactivate?: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
|
|
13
|
+
declare type ConsentIntegrationDefinition = Readonly<{
|
|
14
|
+
id: string;
|
|
15
|
+
useId: string;
|
|
16
|
+
activate: (signal: AbortSignal) => ConsentIntegrationActivation | Promise<ConsentIntegrationActivation>;
|
|
17
|
+
/** Optional bridge for an SDK the application initialized before this manager started. */
|
|
18
|
+
onBlocked?: () => void;
|
|
19
|
+
/** Conservatively require a reload if activation fails after partial SDK initialization. */
|
|
20
|
+
reloadOnError?: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
|
|
23
|
+
/** One configured capture activity per SDK instance; never partitions one client by multiple uses. */
|
|
24
|
+
export declare function createPostHogIntegration(options: PostHogIntegrationOptions): PostHogIntegration;
|
|
25
|
+
|
|
26
|
+
declare type IntegrationDeactivationReason = 'blocked' | 'disposed';
|
|
27
|
+
|
|
28
|
+
/** The small part of posthog-js used by this adapter; posthog-js is app-owned. */
|
|
29
|
+
export declare type PostHogClient = Readonly<{
|
|
30
|
+
init: (token: string, config: PostHogStrictConfig) => unknown;
|
|
31
|
+
opt_in_capturing: (options?: {
|
|
32
|
+
captureEventName: false;
|
|
33
|
+
}) => unknown;
|
|
34
|
+
opt_out_capturing: () => unknown;
|
|
35
|
+
stopSessionRecording?: () => unknown;
|
|
36
|
+
}>;
|
|
37
|
+
|
|
38
|
+
export declare type PostHogIntegration = ConsentIntegrationDefinition & Readonly<{
|
|
39
|
+
/** Available after strict activation; existing-sdk mode returns its supplied client. */
|
|
40
|
+
getClient: () => PostHogClient | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
|
|
43
|
+
export declare type PostHogIntegrationOptions = (Common & Readonly<{
|
|
44
|
+
mode?: 'strict';
|
|
45
|
+
token: string;
|
|
46
|
+
apiHost?: string;
|
|
47
|
+
/** Dynamically import the SDK here; nothing is loaded until consent is granted. */
|
|
48
|
+
loadClient: () => PostHogClient | Promise<PostHogClient>;
|
|
49
|
+
}>) | (Common & Readonly<{
|
|
50
|
+
mode: 'existing-sdk';
|
|
51
|
+
/** Already initialized by the app; pre-consent activity cannot be prevented retroactively. */
|
|
52
|
+
client: PostHogClient;
|
|
53
|
+
}>);
|
|
54
|
+
|
|
55
|
+
export declare type PostHogStrictConfig = Readonly<{
|
|
56
|
+
api_host?: string;
|
|
57
|
+
autocapture: false;
|
|
58
|
+
capture_pageview: false;
|
|
59
|
+
capture_pageleave: false;
|
|
60
|
+
disable_session_recording: true;
|
|
61
|
+
disable_external_dependency_loading: true;
|
|
62
|
+
advanced_disable_flags: true;
|
|
63
|
+
disable_surveys_automatic_display: true;
|
|
64
|
+
disable_web_experiments: true;
|
|
65
|
+
opt_out_capturing_by_default: true;
|
|
66
|
+
}>;
|
|
67
|
+
|
|
68
|
+
export { }
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//#region src/enforcement/providers/posthog/createPostHogIntegration.ts
|
|
2
|
+
function disable(client) {
|
|
3
|
+
let failure;
|
|
4
|
+
try {
|
|
5
|
+
client.opt_out_capturing();
|
|
6
|
+
} catch (error) {
|
|
7
|
+
failure = error;
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
client.stopSessionRecording?.();
|
|
11
|
+
} catch (error) {
|
|
12
|
+
failure ??= error;
|
|
13
|
+
}
|
|
14
|
+
if (failure !== void 0) throw failure;
|
|
15
|
+
}
|
|
16
|
+
/** One configured capture activity per SDK instance; never partitions one client by multiple uses. */
|
|
17
|
+
function createPostHogIntegration(options) {
|
|
18
|
+
if (!options || typeof options.id !== "string" || !options.id.trim() || typeof options.useId !== "string" || !options.useId.trim()) throw new TypeError("Expected non blank integration and use IDs.");
|
|
19
|
+
if (options.mode === "existing-sdk") {
|
|
20
|
+
const client = options.client;
|
|
21
|
+
if (!client || typeof client.opt_in_capturing !== "function" || typeof client.opt_out_capturing !== "function") throw new TypeError("Expected an initialized PostHog client.");
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
id: options.id,
|
|
24
|
+
useId: options.useId,
|
|
25
|
+
onBlocked: () => disable(client),
|
|
26
|
+
activate(signal) {
|
|
27
|
+
if (signal.aborted) return { deactivate: () => {} };
|
|
28
|
+
client.opt_in_capturing({ captureEventName: false });
|
|
29
|
+
return {
|
|
30
|
+
deactivate: () => disable(client),
|
|
31
|
+
reloadOnDeactivate: true
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
getClient: () => client,
|
|
35
|
+
reloadOnError: true
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (options.mode !== void 0 && options.mode !== "strict") throw new TypeError("Expected a PostHog integration mode.");
|
|
39
|
+
if (typeof options.token !== "string" || !options.token.trim() || typeof options.loadClient !== "function") throw new TypeError("Strict PostHog integration requires a token and lazy client loader.");
|
|
40
|
+
if (options.apiHost !== void 0 && (typeof options.apiHost !== "string" || !options.apiHost.trim())) throw new TypeError("Expected a non blank PostHog API host.");
|
|
41
|
+
let activeClient;
|
|
42
|
+
return Object.freeze({
|
|
43
|
+
id: options.id,
|
|
44
|
+
useId: options.useId,
|
|
45
|
+
reloadOnError: true,
|
|
46
|
+
async activate(signal) {
|
|
47
|
+
if (signal.aborted) return { deactivate: () => {} };
|
|
48
|
+
const client = await options.loadClient();
|
|
49
|
+
if (signal.aborted) return {
|
|
50
|
+
deactivate: () => {},
|
|
51
|
+
reloadOnDeactivate: false
|
|
52
|
+
};
|
|
53
|
+
if (!client || typeof client.init !== "function" || typeof client.opt_in_capturing !== "function" || typeof client.opt_out_capturing !== "function") throw new TypeError("Expected a PostHog client with init and capture controls.");
|
|
54
|
+
const config = Object.freeze({
|
|
55
|
+
...options.apiHost === void 0 ? {} : { api_host: options.apiHost },
|
|
56
|
+
autocapture: false,
|
|
57
|
+
capture_pageview: false,
|
|
58
|
+
capture_pageleave: false,
|
|
59
|
+
disable_session_recording: true,
|
|
60
|
+
disable_external_dependency_loading: true,
|
|
61
|
+
advanced_disable_flags: true,
|
|
62
|
+
disable_surveys_automatic_display: true,
|
|
63
|
+
disable_web_experiments: true,
|
|
64
|
+
opt_out_capturing_by_default: true
|
|
65
|
+
});
|
|
66
|
+
try {
|
|
67
|
+
client.init(options.token, config);
|
|
68
|
+
if (signal.aborted) {
|
|
69
|
+
disable(client);
|
|
70
|
+
return {
|
|
71
|
+
deactivate: () => disable(client),
|
|
72
|
+
reloadOnDeactivate: true
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
client.opt_in_capturing({ captureEventName: false });
|
|
76
|
+
activeClient = client;
|
|
77
|
+
return {
|
|
78
|
+
deactivate: () => {
|
|
79
|
+
activeClient = void 0;
|
|
80
|
+
disable(client);
|
|
81
|
+
},
|
|
82
|
+
reloadOnDeactivate: true
|
|
83
|
+
};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
activeClient = void 0;
|
|
86
|
+
try {
|
|
87
|
+
disable(client);
|
|
88
|
+
} catch {}
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
getClient: () => activeClient
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { createPostHogIntegration };
|