@botim/mp-debug-sdk 0.6.2 → 0.7.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/dist/index.cjs +227 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -2
- package/dist/index.d.ts +58 -2
- package/dist/index.js +224 -1
- package/dist/index.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +31 -1
- package/dist/types.d.ts +31 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType, EventLevel, ConsolePayload, NetworkPayload, ErrorPayload, CommandHandler, BotimConfig, ConsentInput, DeviceInfo } from './types.cjs';
|
|
1
|
+
import { ConsentPromptCopy, EventType, EventLevel, ConsolePayload, NetworkPayload, ErrorPayload, CommandHandler, BotimConfig, ConsentInput, DeviceInfo } from './types.cjs';
|
|
2
2
|
export { AttachRequest, AttachResponse, BotimEnv, BridgePayload, CommandAckPayload, CommandContext, CommandPollResponse, CommandRejectedPayload, CommandRequest, DebugEvent, DebugEventBase, ErrorSource, EventMeta, LifecycleEvent, LifecyclePayload, NetworkPhase, PerfPayload, SCHEMA_VERSION, SerializedValue, StreamFrame, UploadAck, UploadBatch } from './types.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -27,6 +27,62 @@ declare class BotimConsentError extends Error {
|
|
|
27
27
|
constructor(message: string);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* In-app consent modal for the debug SDK.
|
|
32
|
+
*
|
|
33
|
+
* Shown on first load when the host opts in via `consent.promptUser:
|
|
34
|
+
* true`. Persists the user's choice in `localStorage` so subsequent
|
|
35
|
+
* loads attach silently (or stay disabled, if declined).
|
|
36
|
+
*
|
|
37
|
+
* Why hand-rolled DOM/CSS instead of pulling in a UI library:
|
|
38
|
+
* • The SDK ships into BOTIM mini-programs whose own bundles already
|
|
39
|
+
* include framework code — adding React/Vue/Lit just for this one
|
|
40
|
+
* dialog would inflate the SDK by an order of magnitude.
|
|
41
|
+
* • The modal must work on any host (Angular, vanilla, Web
|
|
42
|
+
* Components, future frameworks). Plain DOM is the universal
|
|
43
|
+
* baseline.
|
|
44
|
+
* • Style isolation via inline styles + a unique class prefix
|
|
45
|
+
* (`__botim-debug-consent-`) avoids collisions with whatever
|
|
46
|
+
* stylesheet the host has loaded. We deliberately avoid the
|
|
47
|
+
* simpler `style=""` attribute on every element — bundles using
|
|
48
|
+
* CSP `style-src` directives without `'unsafe-inline'` would
|
|
49
|
+
* reject those, breaking the very debug flow we're trying to
|
|
50
|
+
* enable. Instead we inject one <style> with `!important` rules
|
|
51
|
+
* into <head>, which CSP `style-src 'self'` allows.
|
|
52
|
+
*
|
|
53
|
+
* Trust model: this UI is for user-facing transparency, NOT a
|
|
54
|
+
* cryptographic gate. A motivated attacker who controls the page can
|
|
55
|
+
* trivially write to `localStorage` and fake `granted`. The actual
|
|
56
|
+
* defence against unauthorized debug attach is "the SDK isn't shipped
|
|
57
|
+
* in production builds." Treat the consent record like a "remember
|
|
58
|
+
* me" cookie, not a session token.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
type ConsentDecision = 'granted' | 'denied';
|
|
62
|
+
/**
|
|
63
|
+
* Read the cached consent decision for this mp_id. Returns `null` when
|
|
64
|
+
* no decision has been recorded — the caller should prompt.
|
|
65
|
+
*
|
|
66
|
+
* `localStorage.getItem` can throw in some sandboxed contexts (Safari
|
|
67
|
+
* Private Mode historically; some embedded WebViews). Failures are
|
|
68
|
+
* coerced to `null` so the prompt re-shows rather than crashing the
|
|
69
|
+
* SDK on storage hiccups.
|
|
70
|
+
*/
|
|
71
|
+
declare function readConsentDecision(mpId: string): ConsentDecision | null;
|
|
72
|
+
/**
|
|
73
|
+
* Persist a decision. Failures are swallowed for the same reason as
|
|
74
|
+
* `readConsentDecision` — on storage-hostile platforms the SDK should
|
|
75
|
+
* still function for the current session, even if the prompt re-shows
|
|
76
|
+
* next time.
|
|
77
|
+
*/
|
|
78
|
+
declare function writeConsentDecision(mpId: string, decision: ConsentDecision): void;
|
|
79
|
+
/**
|
|
80
|
+
* Clear the cached decision for an mp_id. Exposed so a host can wire
|
|
81
|
+
* a "Revoke debug consent" button into its own settings UI.
|
|
82
|
+
*/
|
|
83
|
+
declare function clearConsentDecision(mpId: string): void;
|
|
84
|
+
declare function promptForConsent(mpId: string, copy?: ConsentPromptCopy): Promise<ConsentDecision>;
|
|
85
|
+
|
|
30
86
|
/**
|
|
31
87
|
* Built-in commands registered automatically when `enableRemoteDebug` runs.
|
|
32
88
|
*
|
|
@@ -242,4 +298,4 @@ declare const DEFAULT_BUFFER_SIZE = 1000;
|
|
|
242
298
|
declare const DEFAULT_MAX_BATCH_SIZE = 50;
|
|
243
299
|
declare function enableRemoteDebug(options: RemoteDebugOptions): Promise<RemoteDebugHandle>;
|
|
244
300
|
|
|
245
|
-
export { type AppInfo, BotimConfig, BotimConfigError, BotimConsentError, type BuiltinHostHooks, CommandHandler, ConsentInput, ConsolePayload, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, type DedupOptions, DeviceInfo, ErrorPayload, EventLevel, EventType, type ExecOptions, NetworkPayload, type RedactionConfig, type RemoteDebugHandle, type RemoteDebugOptions, type SamplingConfig, type SuppressionSummary, enableRemoteDebug, getBOT };
|
|
301
|
+
export { type AppInfo, BotimConfig, BotimConfigError, BotimConsentError, type BuiltinHostHooks, CommandHandler, type ConsentDecision, ConsentInput, ConsentPromptCopy, ConsolePayload, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, type DedupOptions, DeviceInfo, ErrorPayload, EventLevel, EventType, type ExecOptions, NetworkPayload, type RedactionConfig, type RemoteDebugHandle, type RemoteDebugOptions, type SamplingConfig, type SuppressionSummary, clearConsentDecision, enableRemoteDebug, getBOT, promptForConsent, readConsentDecision, writeConsentDecision };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType, EventLevel, ConsolePayload, NetworkPayload, ErrorPayload, CommandHandler, BotimConfig, ConsentInput, DeviceInfo } from './types.js';
|
|
1
|
+
import { ConsentPromptCopy, EventType, EventLevel, ConsolePayload, NetworkPayload, ErrorPayload, CommandHandler, BotimConfig, ConsentInput, DeviceInfo } from './types.js';
|
|
2
2
|
export { AttachRequest, AttachResponse, BotimEnv, BridgePayload, CommandAckPayload, CommandContext, CommandPollResponse, CommandRejectedPayload, CommandRequest, DebugEvent, DebugEventBase, ErrorSource, EventMeta, LifecycleEvent, LifecyclePayload, NetworkPhase, PerfPayload, SCHEMA_VERSION, SerializedValue, StreamFrame, UploadAck, UploadBatch } from './types.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -27,6 +27,62 @@ declare class BotimConsentError extends Error {
|
|
|
27
27
|
constructor(message: string);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* In-app consent modal for the debug SDK.
|
|
32
|
+
*
|
|
33
|
+
* Shown on first load when the host opts in via `consent.promptUser:
|
|
34
|
+
* true`. Persists the user's choice in `localStorage` so subsequent
|
|
35
|
+
* loads attach silently (or stay disabled, if declined).
|
|
36
|
+
*
|
|
37
|
+
* Why hand-rolled DOM/CSS instead of pulling in a UI library:
|
|
38
|
+
* • The SDK ships into BOTIM mini-programs whose own bundles already
|
|
39
|
+
* include framework code — adding React/Vue/Lit just for this one
|
|
40
|
+
* dialog would inflate the SDK by an order of magnitude.
|
|
41
|
+
* • The modal must work on any host (Angular, vanilla, Web
|
|
42
|
+
* Components, future frameworks). Plain DOM is the universal
|
|
43
|
+
* baseline.
|
|
44
|
+
* • Style isolation via inline styles + a unique class prefix
|
|
45
|
+
* (`__botim-debug-consent-`) avoids collisions with whatever
|
|
46
|
+
* stylesheet the host has loaded. We deliberately avoid the
|
|
47
|
+
* simpler `style=""` attribute on every element — bundles using
|
|
48
|
+
* CSP `style-src` directives without `'unsafe-inline'` would
|
|
49
|
+
* reject those, breaking the very debug flow we're trying to
|
|
50
|
+
* enable. Instead we inject one <style> with `!important` rules
|
|
51
|
+
* into <head>, which CSP `style-src 'self'` allows.
|
|
52
|
+
*
|
|
53
|
+
* Trust model: this UI is for user-facing transparency, NOT a
|
|
54
|
+
* cryptographic gate. A motivated attacker who controls the page can
|
|
55
|
+
* trivially write to `localStorage` and fake `granted`. The actual
|
|
56
|
+
* defence against unauthorized debug attach is "the SDK isn't shipped
|
|
57
|
+
* in production builds." Treat the consent record like a "remember
|
|
58
|
+
* me" cookie, not a session token.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
type ConsentDecision = 'granted' | 'denied';
|
|
62
|
+
/**
|
|
63
|
+
* Read the cached consent decision for this mp_id. Returns `null` when
|
|
64
|
+
* no decision has been recorded — the caller should prompt.
|
|
65
|
+
*
|
|
66
|
+
* `localStorage.getItem` can throw in some sandboxed contexts (Safari
|
|
67
|
+
* Private Mode historically; some embedded WebViews). Failures are
|
|
68
|
+
* coerced to `null` so the prompt re-shows rather than crashing the
|
|
69
|
+
* SDK on storage hiccups.
|
|
70
|
+
*/
|
|
71
|
+
declare function readConsentDecision(mpId: string): ConsentDecision | null;
|
|
72
|
+
/**
|
|
73
|
+
* Persist a decision. Failures are swallowed for the same reason as
|
|
74
|
+
* `readConsentDecision` — on storage-hostile platforms the SDK should
|
|
75
|
+
* still function for the current session, even if the prompt re-shows
|
|
76
|
+
* next time.
|
|
77
|
+
*/
|
|
78
|
+
declare function writeConsentDecision(mpId: string, decision: ConsentDecision): void;
|
|
79
|
+
/**
|
|
80
|
+
* Clear the cached decision for an mp_id. Exposed so a host can wire
|
|
81
|
+
* a "Revoke debug consent" button into its own settings UI.
|
|
82
|
+
*/
|
|
83
|
+
declare function clearConsentDecision(mpId: string): void;
|
|
84
|
+
declare function promptForConsent(mpId: string, copy?: ConsentPromptCopy): Promise<ConsentDecision>;
|
|
85
|
+
|
|
30
86
|
/**
|
|
31
87
|
* Built-in commands registered automatically when `enableRemoteDebug` runs.
|
|
32
88
|
*
|
|
@@ -242,4 +298,4 @@ declare const DEFAULT_BUFFER_SIZE = 1000;
|
|
|
242
298
|
declare const DEFAULT_MAX_BATCH_SIZE = 50;
|
|
243
299
|
declare function enableRemoteDebug(options: RemoteDebugOptions): Promise<RemoteDebugHandle>;
|
|
244
300
|
|
|
245
|
-
export { type AppInfo, BotimConfig, BotimConfigError, BotimConsentError, type BuiltinHostHooks, CommandHandler, ConsentInput, ConsolePayload, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, type DedupOptions, DeviceInfo, ErrorPayload, EventLevel, EventType, type ExecOptions, NetworkPayload, type RedactionConfig, type RemoteDebugHandle, type RemoteDebugOptions, type SamplingConfig, type SuppressionSummary, enableRemoteDebug, getBOT };
|
|
301
|
+
export { type AppInfo, BotimConfig, BotimConfigError, BotimConsentError, type BuiltinHostHooks, CommandHandler, type ConsentDecision, ConsentInput, ConsentPromptCopy, ConsolePayload, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, type DedupOptions, DeviceInfo, ErrorPayload, EventLevel, EventType, type ExecOptions, NetworkPayload, type RedactionConfig, type RemoteDebugHandle, type RemoteDebugOptions, type SamplingConfig, type SuppressionSummary, clearConsentDecision, enableRemoteDebug, getBOT, promptForConsent, readConsentDecision, writeConsentDecision };
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,214 @@ var BotimConsentError = class extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
// src/consent-ui.ts
|
|
24
|
+
var STORAGE_PREFIX = "__botim_debug_consent_";
|
|
25
|
+
var CSS_PREFIX = "__botim-debug-consent";
|
|
26
|
+
var STYLE_ELEMENT_ID = `${CSS_PREFIX}-styles`;
|
|
27
|
+
var DEFAULT_COPY = {
|
|
28
|
+
title: "Enable BOTIM debug logging?",
|
|
29
|
+
body: [
|
|
30
|
+
"This shares your screen content, console logs, and network calls with the BOTIM team to help debug this mini-program.",
|
|
31
|
+
"No data leaves your device unless you agree. You can revoke this anytime by clearing site data or via developer tools."
|
|
32
|
+
],
|
|
33
|
+
acceptLabel: "Allow",
|
|
34
|
+
declineLabel: "Skip"
|
|
35
|
+
};
|
|
36
|
+
function readConsentDecision(mpId) {
|
|
37
|
+
if (typeof localStorage === "undefined") return null;
|
|
38
|
+
try {
|
|
39
|
+
const raw = localStorage.getItem(STORAGE_PREFIX + mpId);
|
|
40
|
+
if (raw === "granted" || raw === "denied") return raw;
|
|
41
|
+
return null;
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function writeConsentDecision(mpId, decision) {
|
|
47
|
+
if (typeof localStorage === "undefined") return;
|
|
48
|
+
try {
|
|
49
|
+
localStorage.setItem(STORAGE_PREFIX + mpId, decision);
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function clearConsentDecision(mpId) {
|
|
54
|
+
if (typeof localStorage === "undefined") return;
|
|
55
|
+
try {
|
|
56
|
+
localStorage.removeItem(STORAGE_PREFIX + mpId);
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
var inflightPrompt = null;
|
|
61
|
+
async function promptForConsent(mpId, copy = {}) {
|
|
62
|
+
if (inflightPrompt) return inflightPrompt;
|
|
63
|
+
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
64
|
+
return "denied";
|
|
65
|
+
}
|
|
66
|
+
const merged = {
|
|
67
|
+
title: copy.title ?? DEFAULT_COPY.title,
|
|
68
|
+
body: copy.body ?? DEFAULT_COPY.body,
|
|
69
|
+
acceptLabel: copy.acceptLabel ?? DEFAULT_COPY.acceptLabel,
|
|
70
|
+
declineLabel: copy.declineLabel ?? DEFAULT_COPY.declineLabel
|
|
71
|
+
};
|
|
72
|
+
inflightPrompt = new Promise((resolve) => {
|
|
73
|
+
injectStylesheet();
|
|
74
|
+
const overlay = buildOverlay(merged, (decision) => {
|
|
75
|
+
writeConsentDecision(mpId, decision);
|
|
76
|
+
try {
|
|
77
|
+
overlay.remove();
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
inflightPrompt = null;
|
|
81
|
+
resolve(decision);
|
|
82
|
+
});
|
|
83
|
+
document.body.appendChild(overlay);
|
|
84
|
+
});
|
|
85
|
+
return inflightPrompt;
|
|
86
|
+
}
|
|
87
|
+
function injectStylesheet() {
|
|
88
|
+
if (document.getElementById(STYLE_ELEMENT_ID)) return;
|
|
89
|
+
const style = document.createElement("style");
|
|
90
|
+
style.id = STYLE_ELEMENT_ID;
|
|
91
|
+
style.textContent = `
|
|
92
|
+
.${CSS_PREFIX}-overlay {
|
|
93
|
+
position: fixed !important;
|
|
94
|
+
inset: 0 !important;
|
|
95
|
+
z-index: 2147483647 !important;
|
|
96
|
+
display: flex !important;
|
|
97
|
+
align-items: flex-end !important;
|
|
98
|
+
justify-content: center !important;
|
|
99
|
+
background: rgba(0, 0, 0, 0.45) !important;
|
|
100
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
101
|
+
Roboto, "Helvetica Neue", sans-serif !important;
|
|
102
|
+
animation: ${CSS_PREFIX}-fade-in 160ms ease-out !important;
|
|
103
|
+
box-sizing: border-box !important;
|
|
104
|
+
padding: 16px !important;
|
|
105
|
+
}
|
|
106
|
+
@media (min-width: 480px) {
|
|
107
|
+
.${CSS_PREFIX}-overlay {
|
|
108
|
+
align-items: center !important;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
@keyframes ${CSS_PREFIX}-fade-in {
|
|
112
|
+
from { opacity: 0; }
|
|
113
|
+
to { opacity: 1; }
|
|
114
|
+
}
|
|
115
|
+
.${CSS_PREFIX}-card {
|
|
116
|
+
background: #ffffff !important;
|
|
117
|
+
color: #0e1116 !important;
|
|
118
|
+
border-radius: 16px !important;
|
|
119
|
+
max-width: 420px !important;
|
|
120
|
+
width: 100% !important;
|
|
121
|
+
padding: 20px 20px 16px !important;
|
|
122
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18) !important;
|
|
123
|
+
box-sizing: border-box !important;
|
|
124
|
+
}
|
|
125
|
+
.${CSS_PREFIX}-title {
|
|
126
|
+
font-size: 17px !important;
|
|
127
|
+
font-weight: 600 !important;
|
|
128
|
+
margin: 0 0 12px !important;
|
|
129
|
+
line-height: 1.3 !important;
|
|
130
|
+
}
|
|
131
|
+
.${CSS_PREFIX}-body {
|
|
132
|
+
font-size: 14px !important;
|
|
133
|
+
line-height: 1.5 !important;
|
|
134
|
+
color: #4a5160 !important;
|
|
135
|
+
margin: 0 0 8px !important;
|
|
136
|
+
}
|
|
137
|
+
.${CSS_PREFIX}-actions {
|
|
138
|
+
display: flex !important;
|
|
139
|
+
justify-content: flex-end !important;
|
|
140
|
+
gap: 8px !important;
|
|
141
|
+
margin-top: 16px !important;
|
|
142
|
+
}
|
|
143
|
+
.${CSS_PREFIX}-btn {
|
|
144
|
+
font-family: inherit !important;
|
|
145
|
+
font-size: 14px !important;
|
|
146
|
+
font-weight: 500 !important;
|
|
147
|
+
padding: 9px 16px !important;
|
|
148
|
+
border-radius: 10px !important;
|
|
149
|
+
border: none !important;
|
|
150
|
+
cursor: pointer !important;
|
|
151
|
+
line-height: 1 !important;
|
|
152
|
+
min-height: 36px !important;
|
|
153
|
+
box-sizing: border-box !important;
|
|
154
|
+
}
|
|
155
|
+
.${CSS_PREFIX}-btn-decline {
|
|
156
|
+
background: transparent !important;
|
|
157
|
+
color: #4a5160 !important;
|
|
158
|
+
}
|
|
159
|
+
.${CSS_PREFIX}-btn-decline:hover {
|
|
160
|
+
background: #f3f4f6 !important;
|
|
161
|
+
}
|
|
162
|
+
.${CSS_PREFIX}-btn-accept {
|
|
163
|
+
background: #0066ff !important;
|
|
164
|
+
color: #ffffff !important;
|
|
165
|
+
}
|
|
166
|
+
.${CSS_PREFIX}-btn-accept:hover {
|
|
167
|
+
background: #0055d4 !important;
|
|
168
|
+
}
|
|
169
|
+
@media (prefers-color-scheme: dark) {
|
|
170
|
+
.${CSS_PREFIX}-card {
|
|
171
|
+
background: #1c1f24 !important;
|
|
172
|
+
color: #e8eaed !important;
|
|
173
|
+
}
|
|
174
|
+
.${CSS_PREFIX}-body {
|
|
175
|
+
color: #b9bec7 !important;
|
|
176
|
+
}
|
|
177
|
+
.${CSS_PREFIX}-btn-decline {
|
|
178
|
+
color: #b9bec7 !important;
|
|
179
|
+
}
|
|
180
|
+
.${CSS_PREFIX}-btn-decline:hover {
|
|
181
|
+
background: #2a2e35 !important;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
185
|
+
document.head.appendChild(style);
|
|
186
|
+
}
|
|
187
|
+
function buildOverlay(copy, onDecision) {
|
|
188
|
+
const overlay = document.createElement("div");
|
|
189
|
+
overlay.className = `${CSS_PREFIX}-overlay`;
|
|
190
|
+
overlay.setAttribute("role", "dialog");
|
|
191
|
+
overlay.setAttribute("aria-modal", "true");
|
|
192
|
+
overlay.setAttribute("aria-labelledby", `${CSS_PREFIX}-title`);
|
|
193
|
+
const card = document.createElement("div");
|
|
194
|
+
card.className = `${CSS_PREFIX}-card`;
|
|
195
|
+
const title = document.createElement("h2");
|
|
196
|
+
title.id = `${CSS_PREFIX}-title`;
|
|
197
|
+
title.className = `${CSS_PREFIX}-title`;
|
|
198
|
+
title.textContent = copy.title;
|
|
199
|
+
card.appendChild(title);
|
|
200
|
+
for (const para of copy.body) {
|
|
201
|
+
const p = document.createElement("p");
|
|
202
|
+
p.className = `${CSS_PREFIX}-body`;
|
|
203
|
+
p.textContent = para;
|
|
204
|
+
card.appendChild(p);
|
|
205
|
+
}
|
|
206
|
+
const actions = document.createElement("div");
|
|
207
|
+
actions.className = `${CSS_PREFIX}-actions`;
|
|
208
|
+
const declineBtn = document.createElement("button");
|
|
209
|
+
declineBtn.type = "button";
|
|
210
|
+
declineBtn.className = `${CSS_PREFIX}-btn ${CSS_PREFIX}-btn-decline`;
|
|
211
|
+
declineBtn.textContent = copy.declineLabel;
|
|
212
|
+
declineBtn.addEventListener("click", () => onDecision("denied"));
|
|
213
|
+
const acceptBtn = document.createElement("button");
|
|
214
|
+
acceptBtn.type = "button";
|
|
215
|
+
acceptBtn.className = `${CSS_PREFIX}-btn ${CSS_PREFIX}-btn-accept`;
|
|
216
|
+
acceptBtn.textContent = copy.acceptLabel;
|
|
217
|
+
acceptBtn.addEventListener("click", () => onDecision("granted"));
|
|
218
|
+
actions.appendChild(declineBtn);
|
|
219
|
+
actions.appendChild(acceptBtn);
|
|
220
|
+
card.appendChild(actions);
|
|
221
|
+
overlay.appendChild(card);
|
|
222
|
+
requestAnimationFrame(() => {
|
|
223
|
+
try {
|
|
224
|
+
acceptBtn.focus();
|
|
225
|
+
} catch {
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
return overlay;
|
|
229
|
+
}
|
|
230
|
+
|
|
23
231
|
// src/buffer.ts
|
|
24
232
|
var RingBuffer = class {
|
|
25
233
|
constructor(opts) {
|
|
@@ -1406,6 +1614,21 @@ function assertConfig(config) {
|
|
|
1406
1614
|
async function enableRemoteDebug(options) {
|
|
1407
1615
|
if (options.enabled === false) return NOOP_HANDLE;
|
|
1408
1616
|
assertConfig(options.config);
|
|
1617
|
+
if (options.consent?.promptUser) {
|
|
1618
|
+
const cached = readConsentDecision(options.config.miniProgramId);
|
|
1619
|
+
let decision = cached;
|
|
1620
|
+
if (decision === null) {
|
|
1621
|
+
decision = await promptForConsent(
|
|
1622
|
+
options.config.miniProgramId,
|
|
1623
|
+
options.consent.promptCopy
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
if (decision === "denied") return NOOP_HANDLE;
|
|
1627
|
+
options = {
|
|
1628
|
+
...options,
|
|
1629
|
+
consent: { ...options.consent, userOptIn: true }
|
|
1630
|
+
};
|
|
1631
|
+
}
|
|
1409
1632
|
assertConsent(options.config, options.consent);
|
|
1410
1633
|
const onError = options.onError ?? (() => {
|
|
1411
1634
|
});
|
|
@@ -1599,6 +1822,6 @@ async function enableRemoteDebug(options) {
|
|
|
1599
1822
|
};
|
|
1600
1823
|
}
|
|
1601
1824
|
|
|
1602
|
-
export { BotimConfigError, BotimConsentError, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, SCHEMA_VERSION, enableRemoteDebug, getBOT };
|
|
1825
|
+
export { BotimConfigError, BotimConsentError, DEFAULT_BODY_PATTERNS, DEFAULT_BUFFER_SIZE, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_REDACT_HEADERS, SCHEMA_VERSION, clearConsentDecision, enableRemoteDebug, getBOT, promptForConsent, readConsentDecision, writeConsentDecision };
|
|
1603
1826
|
//# sourceMappingURL=index.js.map
|
|
1604
1827
|
//# sourceMappingURL=index.js.map
|