@botim/mp-debug-sdk 0.6.1 → 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/README.md +16 -1
- 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/README.md
CHANGED
|
@@ -13,10 +13,15 @@ Mini-programs run on user devices in environments you can't easily attach a debu
|
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
16
|
+
> **Heads-up — registry override required in BOTIM repos.**
|
|
17
|
+
> Most BOTIM mini-program repos pin the `@botim` scope to the internal Artifactory mirror (`@botim:registry=https://artifactory.corp.algento.com/artifactory/api/npm/bot-npm/`). This SDK is **published to public npm**, so a plain `npm install @botim/mp-debug-sdk` in those repos will hit Artifactory, not find the package, and 404. Use the public registry explicitly for this one package:
|
|
18
|
+
|
|
16
19
|
```bash
|
|
17
|
-
npm install @botim/mp-debug-sdk
|
|
20
|
+
npm install @botim/mp-debug-sdk --registry=https://registry.npmjs.org/
|
|
18
21
|
```
|
|
19
22
|
|
|
23
|
+
If your repo doesn't have an `@botim` scope override (rare), the flag is harmless — npm uses `registry.npmjs.org` by default. **Don't** add `@botim:registry=https://registry.npmjs.org/` to your `.npmrc`: it would shadow the internal Artifactory registry that other `@botim/*` packages (mp-framework, etc.) need.
|
|
24
|
+
|
|
20
25
|
## 1. Add the env config files
|
|
21
26
|
|
|
22
27
|
Each environment of your mini-program ships with one config file at the project root, in the standard BOTIM mini-program schema:
|
|
@@ -237,6 +242,16 @@ Once your build is wired and shipped, see **[`docs/live-debugging.md`](./docs/li
|
|
|
237
242
|
| `RemoteDebugHandle.flush()` | Force-flush the in-memory buffer. |
|
|
238
243
|
| `RemoteDebugHandle.stop()` | Uninstall and drain the queue. |
|
|
239
244
|
|
|
245
|
+
## AI debug skill (Claude Code)
|
|
246
|
+
|
|
247
|
+
A Claude Code skill that teaches AI agents how to wire and consume this SDK lives at `.claude/skills/botim-debug-relay/SKILL.md`. Open Claude Code from this repo and the skill auto-loads — no setup needed. To use it from anywhere on your machine:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
cp -r .claude/skills/botim-debug-relay ~/.claude/skills/
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
> **The file in this repo is a mirror.** The canonical copy lives in `botim-debug-relay/.claude/skills/botim-debug-relay/SKILL.md`. **Do not edit the SDK-side copy directly** — your changes will be overwritten by the next sync. Edit in the relay repo, then run `bash bin/sync-skill.sh` from that repo to propagate here.
|
|
254
|
+
|
|
240
255
|
## License
|
|
241
256
|
|
|
242
257
|
[ISC](./LICENSE) © BOTIM
|
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,214 @@ var BotimConsentError = class extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
// src/consent-ui.ts
|
|
26
|
+
var STORAGE_PREFIX = "__botim_debug_consent_";
|
|
27
|
+
var CSS_PREFIX = "__botim-debug-consent";
|
|
28
|
+
var STYLE_ELEMENT_ID = `${CSS_PREFIX}-styles`;
|
|
29
|
+
var DEFAULT_COPY = {
|
|
30
|
+
title: "Enable BOTIM debug logging?",
|
|
31
|
+
body: [
|
|
32
|
+
"This shares your screen content, console logs, and network calls with the BOTIM team to help debug this mini-program.",
|
|
33
|
+
"No data leaves your device unless you agree. You can revoke this anytime by clearing site data or via developer tools."
|
|
34
|
+
],
|
|
35
|
+
acceptLabel: "Allow",
|
|
36
|
+
declineLabel: "Skip"
|
|
37
|
+
};
|
|
38
|
+
function readConsentDecision(mpId) {
|
|
39
|
+
if (typeof localStorage === "undefined") return null;
|
|
40
|
+
try {
|
|
41
|
+
const raw = localStorage.getItem(STORAGE_PREFIX + mpId);
|
|
42
|
+
if (raw === "granted" || raw === "denied") return raw;
|
|
43
|
+
return null;
|
|
44
|
+
} catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function writeConsentDecision(mpId, decision) {
|
|
49
|
+
if (typeof localStorage === "undefined") return;
|
|
50
|
+
try {
|
|
51
|
+
localStorage.setItem(STORAGE_PREFIX + mpId, decision);
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function clearConsentDecision(mpId) {
|
|
56
|
+
if (typeof localStorage === "undefined") return;
|
|
57
|
+
try {
|
|
58
|
+
localStorage.removeItem(STORAGE_PREFIX + mpId);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
var inflightPrompt = null;
|
|
63
|
+
async function promptForConsent(mpId, copy = {}) {
|
|
64
|
+
if (inflightPrompt) return inflightPrompt;
|
|
65
|
+
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
66
|
+
return "denied";
|
|
67
|
+
}
|
|
68
|
+
const merged = {
|
|
69
|
+
title: copy.title ?? DEFAULT_COPY.title,
|
|
70
|
+
body: copy.body ?? DEFAULT_COPY.body,
|
|
71
|
+
acceptLabel: copy.acceptLabel ?? DEFAULT_COPY.acceptLabel,
|
|
72
|
+
declineLabel: copy.declineLabel ?? DEFAULT_COPY.declineLabel
|
|
73
|
+
};
|
|
74
|
+
inflightPrompt = new Promise((resolve) => {
|
|
75
|
+
injectStylesheet();
|
|
76
|
+
const overlay = buildOverlay(merged, (decision) => {
|
|
77
|
+
writeConsentDecision(mpId, decision);
|
|
78
|
+
try {
|
|
79
|
+
overlay.remove();
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
inflightPrompt = null;
|
|
83
|
+
resolve(decision);
|
|
84
|
+
});
|
|
85
|
+
document.body.appendChild(overlay);
|
|
86
|
+
});
|
|
87
|
+
return inflightPrompt;
|
|
88
|
+
}
|
|
89
|
+
function injectStylesheet() {
|
|
90
|
+
if (document.getElementById(STYLE_ELEMENT_ID)) return;
|
|
91
|
+
const style = document.createElement("style");
|
|
92
|
+
style.id = STYLE_ELEMENT_ID;
|
|
93
|
+
style.textContent = `
|
|
94
|
+
.${CSS_PREFIX}-overlay {
|
|
95
|
+
position: fixed !important;
|
|
96
|
+
inset: 0 !important;
|
|
97
|
+
z-index: 2147483647 !important;
|
|
98
|
+
display: flex !important;
|
|
99
|
+
align-items: flex-end !important;
|
|
100
|
+
justify-content: center !important;
|
|
101
|
+
background: rgba(0, 0, 0, 0.45) !important;
|
|
102
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
103
|
+
Roboto, "Helvetica Neue", sans-serif !important;
|
|
104
|
+
animation: ${CSS_PREFIX}-fade-in 160ms ease-out !important;
|
|
105
|
+
box-sizing: border-box !important;
|
|
106
|
+
padding: 16px !important;
|
|
107
|
+
}
|
|
108
|
+
@media (min-width: 480px) {
|
|
109
|
+
.${CSS_PREFIX}-overlay {
|
|
110
|
+
align-items: center !important;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
@keyframes ${CSS_PREFIX}-fade-in {
|
|
114
|
+
from { opacity: 0; }
|
|
115
|
+
to { opacity: 1; }
|
|
116
|
+
}
|
|
117
|
+
.${CSS_PREFIX}-card {
|
|
118
|
+
background: #ffffff !important;
|
|
119
|
+
color: #0e1116 !important;
|
|
120
|
+
border-radius: 16px !important;
|
|
121
|
+
max-width: 420px !important;
|
|
122
|
+
width: 100% !important;
|
|
123
|
+
padding: 20px 20px 16px !important;
|
|
124
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18) !important;
|
|
125
|
+
box-sizing: border-box !important;
|
|
126
|
+
}
|
|
127
|
+
.${CSS_PREFIX}-title {
|
|
128
|
+
font-size: 17px !important;
|
|
129
|
+
font-weight: 600 !important;
|
|
130
|
+
margin: 0 0 12px !important;
|
|
131
|
+
line-height: 1.3 !important;
|
|
132
|
+
}
|
|
133
|
+
.${CSS_PREFIX}-body {
|
|
134
|
+
font-size: 14px !important;
|
|
135
|
+
line-height: 1.5 !important;
|
|
136
|
+
color: #4a5160 !important;
|
|
137
|
+
margin: 0 0 8px !important;
|
|
138
|
+
}
|
|
139
|
+
.${CSS_PREFIX}-actions {
|
|
140
|
+
display: flex !important;
|
|
141
|
+
justify-content: flex-end !important;
|
|
142
|
+
gap: 8px !important;
|
|
143
|
+
margin-top: 16px !important;
|
|
144
|
+
}
|
|
145
|
+
.${CSS_PREFIX}-btn {
|
|
146
|
+
font-family: inherit !important;
|
|
147
|
+
font-size: 14px !important;
|
|
148
|
+
font-weight: 500 !important;
|
|
149
|
+
padding: 9px 16px !important;
|
|
150
|
+
border-radius: 10px !important;
|
|
151
|
+
border: none !important;
|
|
152
|
+
cursor: pointer !important;
|
|
153
|
+
line-height: 1 !important;
|
|
154
|
+
min-height: 36px !important;
|
|
155
|
+
box-sizing: border-box !important;
|
|
156
|
+
}
|
|
157
|
+
.${CSS_PREFIX}-btn-decline {
|
|
158
|
+
background: transparent !important;
|
|
159
|
+
color: #4a5160 !important;
|
|
160
|
+
}
|
|
161
|
+
.${CSS_PREFIX}-btn-decline:hover {
|
|
162
|
+
background: #f3f4f6 !important;
|
|
163
|
+
}
|
|
164
|
+
.${CSS_PREFIX}-btn-accept {
|
|
165
|
+
background: #0066ff !important;
|
|
166
|
+
color: #ffffff !important;
|
|
167
|
+
}
|
|
168
|
+
.${CSS_PREFIX}-btn-accept:hover {
|
|
169
|
+
background: #0055d4 !important;
|
|
170
|
+
}
|
|
171
|
+
@media (prefers-color-scheme: dark) {
|
|
172
|
+
.${CSS_PREFIX}-card {
|
|
173
|
+
background: #1c1f24 !important;
|
|
174
|
+
color: #e8eaed !important;
|
|
175
|
+
}
|
|
176
|
+
.${CSS_PREFIX}-body {
|
|
177
|
+
color: #b9bec7 !important;
|
|
178
|
+
}
|
|
179
|
+
.${CSS_PREFIX}-btn-decline {
|
|
180
|
+
color: #b9bec7 !important;
|
|
181
|
+
}
|
|
182
|
+
.${CSS_PREFIX}-btn-decline:hover {
|
|
183
|
+
background: #2a2e35 !important;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
`;
|
|
187
|
+
document.head.appendChild(style);
|
|
188
|
+
}
|
|
189
|
+
function buildOverlay(copy, onDecision) {
|
|
190
|
+
const overlay = document.createElement("div");
|
|
191
|
+
overlay.className = `${CSS_PREFIX}-overlay`;
|
|
192
|
+
overlay.setAttribute("role", "dialog");
|
|
193
|
+
overlay.setAttribute("aria-modal", "true");
|
|
194
|
+
overlay.setAttribute("aria-labelledby", `${CSS_PREFIX}-title`);
|
|
195
|
+
const card = document.createElement("div");
|
|
196
|
+
card.className = `${CSS_PREFIX}-card`;
|
|
197
|
+
const title = document.createElement("h2");
|
|
198
|
+
title.id = `${CSS_PREFIX}-title`;
|
|
199
|
+
title.className = `${CSS_PREFIX}-title`;
|
|
200
|
+
title.textContent = copy.title;
|
|
201
|
+
card.appendChild(title);
|
|
202
|
+
for (const para of copy.body) {
|
|
203
|
+
const p = document.createElement("p");
|
|
204
|
+
p.className = `${CSS_PREFIX}-body`;
|
|
205
|
+
p.textContent = para;
|
|
206
|
+
card.appendChild(p);
|
|
207
|
+
}
|
|
208
|
+
const actions = document.createElement("div");
|
|
209
|
+
actions.className = `${CSS_PREFIX}-actions`;
|
|
210
|
+
const declineBtn = document.createElement("button");
|
|
211
|
+
declineBtn.type = "button";
|
|
212
|
+
declineBtn.className = `${CSS_PREFIX}-btn ${CSS_PREFIX}-btn-decline`;
|
|
213
|
+
declineBtn.textContent = copy.declineLabel;
|
|
214
|
+
declineBtn.addEventListener("click", () => onDecision("denied"));
|
|
215
|
+
const acceptBtn = document.createElement("button");
|
|
216
|
+
acceptBtn.type = "button";
|
|
217
|
+
acceptBtn.className = `${CSS_PREFIX}-btn ${CSS_PREFIX}-btn-accept`;
|
|
218
|
+
acceptBtn.textContent = copy.acceptLabel;
|
|
219
|
+
acceptBtn.addEventListener("click", () => onDecision("granted"));
|
|
220
|
+
actions.appendChild(declineBtn);
|
|
221
|
+
actions.appendChild(acceptBtn);
|
|
222
|
+
card.appendChild(actions);
|
|
223
|
+
overlay.appendChild(card);
|
|
224
|
+
requestAnimationFrame(() => {
|
|
225
|
+
try {
|
|
226
|
+
acceptBtn.focus();
|
|
227
|
+
} catch {
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
return overlay;
|
|
231
|
+
}
|
|
232
|
+
|
|
25
233
|
// src/buffer.ts
|
|
26
234
|
var RingBuffer = class {
|
|
27
235
|
constructor(opts) {
|
|
@@ -1408,6 +1616,21 @@ function assertConfig(config) {
|
|
|
1408
1616
|
async function enableRemoteDebug(options) {
|
|
1409
1617
|
if (options.enabled === false) return NOOP_HANDLE;
|
|
1410
1618
|
assertConfig(options.config);
|
|
1619
|
+
if (options.consent?.promptUser) {
|
|
1620
|
+
const cached = readConsentDecision(options.config.miniProgramId);
|
|
1621
|
+
let decision = cached;
|
|
1622
|
+
if (decision === null) {
|
|
1623
|
+
decision = await promptForConsent(
|
|
1624
|
+
options.config.miniProgramId,
|
|
1625
|
+
options.consent.promptCopy
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
if (decision === "denied") return NOOP_HANDLE;
|
|
1629
|
+
options = {
|
|
1630
|
+
...options,
|
|
1631
|
+
consent: { ...options.consent, userOptIn: true }
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1411
1634
|
assertConsent(options.config, options.consent);
|
|
1412
1635
|
const onError = options.onError ?? (() => {
|
|
1413
1636
|
});
|
|
@@ -1610,7 +1833,11 @@ exports.DEFAULT_MAX_BATCH_SIZE = DEFAULT_MAX_BATCH_SIZE;
|
|
|
1610
1833
|
exports.DEFAULT_MAX_BODY_BYTES = DEFAULT_MAX_BODY_BYTES;
|
|
1611
1834
|
exports.DEFAULT_REDACT_HEADERS = DEFAULT_REDACT_HEADERS;
|
|
1612
1835
|
exports.SCHEMA_VERSION = SCHEMA_VERSION;
|
|
1836
|
+
exports.clearConsentDecision = clearConsentDecision;
|
|
1613
1837
|
exports.enableRemoteDebug = enableRemoteDebug;
|
|
1614
1838
|
exports.getBOT = getBOT;
|
|
1839
|
+
exports.promptForConsent = promptForConsent;
|
|
1840
|
+
exports.readConsentDecision = readConsentDecision;
|
|
1841
|
+
exports.writeConsentDecision = writeConsentDecision;
|
|
1615
1842
|
//# sourceMappingURL=index.cjs.map
|
|
1616
1843
|
//# sourceMappingURL=index.cjs.map
|