@merittdev/horus-lens 0.4.0 → 0.5.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.
- package/dist/browser.cjs +449 -190
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +2 -2
- package/dist/{chunk-B7QI3T3E.js → chunk-GVULQ2IF.js} +85 -21
- package/dist/{chunk-B7QI3T3E.js.map → chunk-GVULQ2IF.js.map} +1 -1
- package/dist/{chunk-GQREYSHC.js → chunk-MN44USB4.js} +367 -172
- package/dist/chunk-MN44USB4.js.map +1 -0
- package/dist/cli.cjs +25 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +84 -20
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-Dyzc1E9T.d.ts → index.d-BYuZWEkh.d.ts} +7 -0
- package/dist/{index.d-BYG_Mjs-.d.cts → index.d-DeJ1mfh0.d.cts} +7 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/dist/lens.min.js +204 -130
- package/dist/react.cjs +449 -190
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +2 -2
- package/package.json +3 -2
- package/dist/chunk-GQREYSHC.js.map +0 -1
- package/dist/lens.min.js.map +0 -1
package/dist/browser.d.cts
CHANGED
package/dist/browser.d.ts
CHANGED
package/dist/browser.js
CHANGED
|
@@ -29063,7 +29063,7 @@ async function domToBlob(node2, options) {
|
|
|
29063
29063
|
|
|
29064
29064
|
// ../core/dist/index.js
|
|
29065
29065
|
var SDK_NAME = "@merittdev/horus-lens";
|
|
29066
|
-
var SDK_VERSION = true ? "0.
|
|
29066
|
+
var SDK_VERSION = true ? "0.5.1" : "0.0.0-dev";
|
|
29067
29067
|
var DEFAULT_ENDPOINT = "https://api.horus.sh";
|
|
29068
29068
|
var DEFAULT_REPLAY_WINDOW_MS = 15e3;
|
|
29069
29069
|
var DEFAULT_MAX_CONSOLE_ENTRIES = 200;
|
|
@@ -29124,11 +29124,15 @@ function startAutoCapture(client, options = {}) {
|
|
|
29124
29124
|
const last = lastSeen.get(signature);
|
|
29125
29125
|
if (last !== void 0 && now - last < AUTO_CAPTURE_COOLDOWN_MS) return;
|
|
29126
29126
|
if (sessionCount >= AUTO_CAPTURE_SESSION_CAP) return;
|
|
29127
|
+
const previousSeen = lastSeen.get(signature);
|
|
29127
29128
|
lastSeen.set(signature, now);
|
|
29128
29129
|
sessionCount += 1;
|
|
29129
29130
|
submitting = true;
|
|
29130
29131
|
options.onCapture?.(signature);
|
|
29131
29132
|
void Promise.resolve().then(() => client.submitReport({ trigger: "error", include: { screenshot: false } })).catch(() => {
|
|
29133
|
+
if (previousSeen === void 0) lastSeen.delete(signature);
|
|
29134
|
+
else lastSeen.set(signature, previousSeen);
|
|
29135
|
+
sessionCount -= 1;
|
|
29132
29136
|
}).finally(() => {
|
|
29133
29137
|
submitting = false;
|
|
29134
29138
|
});
|
|
@@ -29183,6 +29187,14 @@ var RingBuffer = class {
|
|
|
29183
29187
|
return this.items.length;
|
|
29184
29188
|
}
|
|
29185
29189
|
};
|
|
29190
|
+
var HttpError = class extends Error {
|
|
29191
|
+
constructor(status, message) {
|
|
29192
|
+
super(message);
|
|
29193
|
+
this.status = status;
|
|
29194
|
+
this.name = "HttpError";
|
|
29195
|
+
}
|
|
29196
|
+
status;
|
|
29197
|
+
};
|
|
29186
29198
|
var Transport = class {
|
|
29187
29199
|
constructor(config2) {
|
|
29188
29200
|
this.config = config2;
|
|
@@ -29190,18 +29202,23 @@ var Transport = class {
|
|
|
29190
29202
|
config;
|
|
29191
29203
|
async initiate(assets) {
|
|
29192
29204
|
const body = { accessId: this.config.accessId, assets };
|
|
29193
|
-
return this.postJson(
|
|
29205
|
+
return this.postJson(
|
|
29206
|
+
`${this.config.endpoint}/v1/reports/initiate`,
|
|
29207
|
+
body,
|
|
29208
|
+
{ retries: 0 }
|
|
29209
|
+
);
|
|
29194
29210
|
}
|
|
29195
29211
|
/** Record a late-uploaded asset (background screenshot) on a finalized report. */
|
|
29196
29212
|
async attachAsset(reportId, asset) {
|
|
29197
29213
|
const body = { accessId: this.config.accessId, ...asset };
|
|
29198
29214
|
await this.postJson(`${this.config.endpoint}/v1/reports/${encodeURIComponent(reportId)}/assets`, body);
|
|
29199
29215
|
}
|
|
29200
|
-
async uploadAsset(upload, blob2) {
|
|
29216
|
+
async uploadAsset(upload, blob2, signal) {
|
|
29201
29217
|
const response = await fetch(upload.url, {
|
|
29202
29218
|
method: upload.method,
|
|
29203
29219
|
headers: upload.headers,
|
|
29204
|
-
body: blob2
|
|
29220
|
+
body: blob2,
|
|
29221
|
+
signal
|
|
29205
29222
|
});
|
|
29206
29223
|
if (!response.ok) {
|
|
29207
29224
|
throw new Error(`Asset upload failed (${upload.kind}): ${response.status}`);
|
|
@@ -29209,12 +29226,20 @@ var Transport = class {
|
|
|
29209
29226
|
}
|
|
29210
29227
|
async finalize(reportId, metadata, uploadedAssets) {
|
|
29211
29228
|
const body = { accessId: this.config.accessId, metadata, uploadedAssets };
|
|
29212
|
-
|
|
29213
|
-
|
|
29214
|
-
|
|
29215
|
-
|
|
29229
|
+
try {
|
|
29230
|
+
return await this.postJson(
|
|
29231
|
+
`${this.config.endpoint}/v1/reports/${reportId}/finalize`,
|
|
29232
|
+
body
|
|
29233
|
+
);
|
|
29234
|
+
} catch (err) {
|
|
29235
|
+
if (err instanceof HttpError && err.status === 409) {
|
|
29236
|
+
return { reportId, status: "submitted" };
|
|
29237
|
+
}
|
|
29238
|
+
throw err;
|
|
29239
|
+
}
|
|
29216
29240
|
}
|
|
29217
|
-
async postJson(url2, body,
|
|
29241
|
+
async postJson(url2, body, opts = {}) {
|
|
29242
|
+
const retries = opts.retries ?? 1;
|
|
29218
29243
|
let lastError;
|
|
29219
29244
|
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
29220
29245
|
try {
|
|
@@ -29225,7 +29250,10 @@ var Transport = class {
|
|
|
29225
29250
|
});
|
|
29226
29251
|
if (!response.ok) {
|
|
29227
29252
|
const text = await response.text().catch(() => "");
|
|
29228
|
-
throw new
|
|
29253
|
+
throw new HttpError(
|
|
29254
|
+
response.status,
|
|
29255
|
+
`Request to ${url2} failed: ${response.status} ${text}`.trim()
|
|
29256
|
+
);
|
|
29229
29257
|
}
|
|
29230
29258
|
return await response.json();
|
|
29231
29259
|
} catch (err) {
|
|
@@ -29616,8 +29644,11 @@ function computeCropRect(crop, scale, rasterWidth, rasterHeight) {
|
|
|
29616
29644
|
async function captureScreenshot(excludeHost, crop, composite) {
|
|
29617
29645
|
if (typeof document === "undefined" || typeof window === "undefined") return null;
|
|
29618
29646
|
try {
|
|
29619
|
-
const
|
|
29620
|
-
const
|
|
29647
|
+
const viewportOnly = !composite && !crop;
|
|
29648
|
+
const captureW = composite ? composite.docWidth : window.innerWidth;
|
|
29649
|
+
const captureH = composite ? composite.docHeight : window.innerHeight;
|
|
29650
|
+
const capturePixels = captureW * captureH || 1;
|
|
29651
|
+
const pixelCap = Math.sqrt(SCREENSHOT_MAX_PIXELS / capturePixels);
|
|
29621
29652
|
const scale = Math.max(1, Math.min(window.devicePixelRatio || 1, SCREENSHOT_MAX_SCALE, pixelCap));
|
|
29622
29653
|
const capture = domToBlob(document.documentElement, {
|
|
29623
29654
|
scale,
|
|
@@ -29626,12 +29657,19 @@ async function captureScreenshot(excludeHost, crop, composite) {
|
|
|
29626
29657
|
// JPEG has no alpha — transparent page regions (and any capture box
|
|
29627
29658
|
// extending past short content) would otherwise encode as BLACK.
|
|
29628
29659
|
backgroundColor: "#ffffff",
|
|
29629
|
-
//
|
|
29630
|
-
//
|
|
29631
|
-
// sizes from documentElement's bounding box, which on pages SHORTER than
|
|
29632
|
-
// the viewport is the content height only — marks drawn in the lower
|
|
29633
|
-
// viewport band would fall off the raster and the crop would clamp short.
|
|
29660
|
+
// Composite (annotations): force the capture box to the editor's document
|
|
29661
|
+
// measurement so marks in the lower viewport band aren't clipped.
|
|
29634
29662
|
...composite ? { width: composite.docWidth, height: composite.docHeight } : {},
|
|
29663
|
+
// Plain report: clip the render to the viewport and shift the scrolled
|
|
29664
|
+
// content into it, so only the visible region is rasterized/fetched.
|
|
29665
|
+
...viewportOnly ? {
|
|
29666
|
+
width: window.innerWidth,
|
|
29667
|
+
height: window.innerHeight,
|
|
29668
|
+
style: {
|
|
29669
|
+
transform: `translate(${-window.scrollX}px, ${-window.scrollY}px)`,
|
|
29670
|
+
transformOrigin: "top left"
|
|
29671
|
+
}
|
|
29672
|
+
} : {},
|
|
29635
29673
|
// Exclude the overlay from the capture CLONE — never hide the live node.
|
|
29636
29674
|
filter: (node2) => node2 !== excludeHost,
|
|
29637
29675
|
// Per-resource fetch budget: a single slow cross-origin image must not
|
|
@@ -30101,12 +30139,22 @@ var LensClient = class {
|
|
|
30101
30139
|
input2.screenshotCrop,
|
|
30102
30140
|
input2.annotationComposite
|
|
30103
30141
|
) : Promise.resolve(null);
|
|
30142
|
+
const consumingManualRecording = wantReplay && (this.replay?.hasManualRecording() ?? false) && !(this.replay?.isManualRecording() ?? false);
|
|
30104
30143
|
const replayEvents = wantReplay ? this.replay?.snapshot() ?? [] : [];
|
|
30105
30144
|
const errorEntries = this.errorBuffer.drain();
|
|
30106
|
-
const consoleTail = this.consoleBuffer.tail(CONSOLE_TAIL_SIZE);
|
|
30107
|
-
const networkTail = this.networkBuffer.tail(NETWORK_TAIL_SIZE);
|
|
30108
30145
|
const consoleEntries = this.consoleBuffer.drain();
|
|
30109
30146
|
const networkEntries = this.networkBuffer.drain();
|
|
30147
|
+
this.errorBuffer.clear();
|
|
30148
|
+
this.consoleBuffer.clear();
|
|
30149
|
+
this.networkBuffer.clear();
|
|
30150
|
+
const consoleTail = consoleEntries.slice(-CONSOLE_TAIL_SIZE);
|
|
30151
|
+
const isNetFailure = (e) => e.ok !== true || Boolean(e.error);
|
|
30152
|
+
const recentFailures = networkEntries.filter(isNetFailure).slice(-NETWORK_TAIL_SIZE);
|
|
30153
|
+
const keep = /* @__PURE__ */ new Set([
|
|
30154
|
+
...recentFailures,
|
|
30155
|
+
...networkEntries.slice(-NETWORK_TAIL_SIZE)
|
|
30156
|
+
]);
|
|
30157
|
+
const networkTail = networkEntries.filter((e) => keep.has(e)).slice(-NETWORK_TAIL_SIZE);
|
|
30110
30158
|
let metadata = {
|
|
30111
30159
|
annotations: input2.annotations ?? [],
|
|
30112
30160
|
env: collectEnv(),
|
|
@@ -30160,13 +30208,14 @@ var LensClient = class {
|
|
|
30160
30208
|
}
|
|
30161
30209
|
if (!asset.blob) continue;
|
|
30162
30210
|
try {
|
|
30163
|
-
await this.
|
|
30211
|
+
await this.uploadAssetWithTimeout(upload, asset.blob);
|
|
30164
30212
|
uploadedAssets.push({ kind: upload.kind, key: upload.key, byteSize: asset.blob.size });
|
|
30165
30213
|
} catch (err) {
|
|
30166
30214
|
this.warn(`asset upload failed (${upload.kind})`, err);
|
|
30167
30215
|
}
|
|
30168
30216
|
}
|
|
30169
30217
|
const finalized = await this.transport.finalize(initiated.reportId, metadata, uploadedAssets);
|
|
30218
|
+
if (consumingManualRecording) this.replay?.discardManualRecording();
|
|
30170
30219
|
if (screenshotUpload) {
|
|
30171
30220
|
const upload = screenshotUpload;
|
|
30172
30221
|
void screenshotPromise.then(async (blob2) => {
|
|
@@ -30184,6 +30233,21 @@ var LensClient = class {
|
|
|
30184
30233
|
}
|
|
30185
30234
|
return { reportId: finalized.reportId };
|
|
30186
30235
|
}
|
|
30236
|
+
/**
|
|
30237
|
+
* Upload a foreground asset with a bounded timeout. Without this a stuck S3
|
|
30238
|
+
* PUT (dropped connection, half-open socket) would hang `submitReport`
|
|
30239
|
+
* forever; the timeout aborts the individual PUT so it fails as one asset
|
|
30240
|
+
* (caught by the caller) instead of wedging the whole submit.
|
|
30241
|
+
*/
|
|
30242
|
+
async uploadAssetWithTimeout(upload, blob2) {
|
|
30243
|
+
const controller = new AbortController();
|
|
30244
|
+
const timer = setTimeout(() => controller.abort(), SCREENSHOT_TIMEOUT_MS);
|
|
30245
|
+
try {
|
|
30246
|
+
await this.transport.uploadAsset(upload, blob2, controller.signal);
|
|
30247
|
+
} finally {
|
|
30248
|
+
clearTimeout(timer);
|
|
30249
|
+
}
|
|
30250
|
+
}
|
|
30187
30251
|
warn(message, err) {
|
|
30188
30252
|
if (!this.debug) return;
|
|
30189
30253
|
if (err !== void 0) console.warn(`[lens] ${message}`, err);
|
|
@@ -30241,4 +30305,4 @@ rrweb/dist/rrweb.js:
|
|
|
30241
30305
|
PERFORMANCE OF THIS SOFTWARE.
|
|
30242
30306
|
***************************************************************************** *)
|
|
30243
30307
|
*/
|
|
30244
|
-
//# sourceMappingURL=chunk-
|
|
30308
|
+
//# sourceMappingURL=chunk-GVULQ2IF.js.map
|