@mushi-mushi/core 0.8.0 → 1.0.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 +10 -2
- package/SECURITY.md +167 -4
- package/dist/index.cjs +220 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +469 -2
- package/dist/index.d.ts +469 -2
- package/dist/index.js +219 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -119,6 +119,15 @@ function createApiClient(options) {
|
|
|
119
119
|
const query = new URLSearchParams({ package: packageName }).toString();
|
|
120
120
|
return request("GET", `/v1/sdk/latest-version?${query}`, void 0, maxRetries, "sdk-config");
|
|
121
121
|
},
|
|
122
|
+
async postDiscoveryEvent(event) {
|
|
123
|
+
return request(
|
|
124
|
+
"POST",
|
|
125
|
+
"/v1/sdk/discovery",
|
|
126
|
+
event,
|
|
127
|
+
1,
|
|
128
|
+
"discovery"
|
|
129
|
+
);
|
|
130
|
+
},
|
|
122
131
|
async listReporterReports(reporterToken) {
|
|
123
132
|
return requestForReporter("GET", "/v1/reporter/reports", reporterToken);
|
|
124
133
|
},
|
|
@@ -774,6 +783,8 @@ function captureEnvironment() {
|
|
|
774
783
|
const nav = typeof navigator !== "undefined" ? navigator : void 0;
|
|
775
784
|
const win = typeof window !== "undefined" ? window : void 0;
|
|
776
785
|
const doc = typeof document !== "undefined" ? document : void 0;
|
|
786
|
+
const scr = typeof screen !== "undefined" ? screen : void 0;
|
|
787
|
+
void kickOffUserAgentData(nav);
|
|
777
788
|
const connection = nav && "connection" in nav ? nav.connection : void 0;
|
|
778
789
|
return {
|
|
779
790
|
userAgent: nav?.userAgent ?? "unknown",
|
|
@@ -793,9 +804,146 @@ function captureEnvironment() {
|
|
|
793
804
|
rtt: connection.rtt
|
|
794
805
|
} : void 0,
|
|
795
806
|
deviceMemory: nav?.deviceMemory,
|
|
796
|
-
hardwareConcurrency: nav?.hardwareConcurrency
|
|
807
|
+
hardwareConcurrency: nav?.hardwareConcurrency,
|
|
808
|
+
route: win?.location?.pathname,
|
|
809
|
+
nearestTestid: findNearestTestidFromActive(doc),
|
|
810
|
+
userAgentData: captureUserAgentData(nav),
|
|
811
|
+
screen: captureScreen(scr, win),
|
|
812
|
+
prefersColorScheme: matchScheme(win),
|
|
813
|
+
prefersReducedMotion: matchMedia(win, "(prefers-reduced-motion: reduce)"),
|
|
814
|
+
prefersReducedData: matchMedia(win, "(prefers-reduced-data: reduce)"),
|
|
815
|
+
prefersContrast: matchContrast(win),
|
|
816
|
+
forcedColors: matchMedia(win, "(forced-colors: active)"),
|
|
817
|
+
online: typeof nav?.onLine === "boolean" ? nav.onLine : void 0,
|
|
818
|
+
displayMode: matchDisplayMode(win),
|
|
819
|
+
documentTitle: doc?.title?.slice(0, 200),
|
|
820
|
+
buildId: readBuildIdMeta(doc),
|
|
821
|
+
pageLoadTiming: capturePageLoadTiming(win)
|
|
797
822
|
};
|
|
798
823
|
}
|
|
824
|
+
function findNearestTestidFromActive(doc) {
|
|
825
|
+
if (!doc) return void 0;
|
|
826
|
+
let cur = doc.activeElement ?? null;
|
|
827
|
+
let hops = 0;
|
|
828
|
+
while (cur && hops < 20) {
|
|
829
|
+
const tid = cur.getAttribute?.("data-testid");
|
|
830
|
+
if (tid) return tid;
|
|
831
|
+
cur = cur.parentElement;
|
|
832
|
+
hops++;
|
|
833
|
+
}
|
|
834
|
+
return void 0;
|
|
835
|
+
}
|
|
836
|
+
var cachedHighEntropy = null;
|
|
837
|
+
var highEntropyKickedOff = false;
|
|
838
|
+
function kickOffUserAgentData(nav) {
|
|
839
|
+
if (highEntropyKickedOff) return;
|
|
840
|
+
const ua = nav?.userAgentData;
|
|
841
|
+
if (!ua?.getHighEntropyValues) return;
|
|
842
|
+
highEntropyKickedOff = true;
|
|
843
|
+
ua.getHighEntropyValues([
|
|
844
|
+
"architecture",
|
|
845
|
+
"bitness",
|
|
846
|
+
"model",
|
|
847
|
+
"platformVersion",
|
|
848
|
+
"uaFullVersion",
|
|
849
|
+
"fullVersionList"
|
|
850
|
+
]).then((v) => {
|
|
851
|
+
cachedHighEntropy = v;
|
|
852
|
+
}).catch(() => {
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
function pickBrand(brands) {
|
|
856
|
+
if (!brands?.length) return void 0;
|
|
857
|
+
const real = brands.filter((b) => !/not.?a.?brand/i.test(b.brand));
|
|
858
|
+
if (real.length === 0) return void 0;
|
|
859
|
+
const named = real.find((b) => !/chromium|google chrome/i.test(b.brand));
|
|
860
|
+
return named ?? real[0];
|
|
861
|
+
}
|
|
862
|
+
function captureUserAgentData(nav) {
|
|
863
|
+
const low = nav?.userAgentData;
|
|
864
|
+
if (!low && !cachedHighEntropy) return void 0;
|
|
865
|
+
const fullList = cachedHighEntropy?.fullVersionList;
|
|
866
|
+
const brand = pickBrand(fullList ?? low?.brands);
|
|
867
|
+
const out = {};
|
|
868
|
+
if (brand) {
|
|
869
|
+
out.browser = brand.brand;
|
|
870
|
+
out.browserVersion = brand.version;
|
|
871
|
+
}
|
|
872
|
+
if (low?.platform) out.os = low.platform;
|
|
873
|
+
if (cachedHighEntropy?.platformVersion) out.osVersion = cachedHighEntropy.platformVersion;
|
|
874
|
+
if (typeof low?.mobile === "boolean") out.mobile = low.mobile;
|
|
875
|
+
if (cachedHighEntropy?.model) out.model = cachedHighEntropy.model;
|
|
876
|
+
if (cachedHighEntropy?.architecture) out.architecture = cachedHighEntropy.architecture;
|
|
877
|
+
if (cachedHighEntropy?.bitness) out.bitness = cachedHighEntropy.bitness;
|
|
878
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
879
|
+
}
|
|
880
|
+
function captureScreen(scr, win) {
|
|
881
|
+
if (!scr && !win) return void 0;
|
|
882
|
+
const out = {};
|
|
883
|
+
if (typeof scr?.width === "number") out.width = scr.width;
|
|
884
|
+
if (typeof scr?.height === "number") out.height = scr.height;
|
|
885
|
+
if (typeof win?.devicePixelRatio === "number") out.devicePixelRatio = win.devicePixelRatio;
|
|
886
|
+
if (typeof scr?.colorDepth === "number") out.colorDepth = scr.colorDepth;
|
|
887
|
+
const orientationType = scr?.orientation?.type;
|
|
888
|
+
if (orientationType) out.orientation = orientationType;
|
|
889
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
890
|
+
}
|
|
891
|
+
function matchMedia(win, query) {
|
|
892
|
+
if (!win?.matchMedia) return void 0;
|
|
893
|
+
try {
|
|
894
|
+
return win.matchMedia(query).matches;
|
|
895
|
+
} catch {
|
|
896
|
+
return void 0;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function matchScheme(win) {
|
|
900
|
+
if (!win?.matchMedia) return void 0;
|
|
901
|
+
if (matchMedia(win, "(prefers-color-scheme: dark)")) return "dark";
|
|
902
|
+
if (matchMedia(win, "(prefers-color-scheme: light)")) return "light";
|
|
903
|
+
return "no-preference";
|
|
904
|
+
}
|
|
905
|
+
function matchContrast(win) {
|
|
906
|
+
if (!win?.matchMedia) return void 0;
|
|
907
|
+
if (matchMedia(win, "(prefers-contrast: more)")) return "more";
|
|
908
|
+
if (matchMedia(win, "(prefers-contrast: less)")) return "less";
|
|
909
|
+
if (matchMedia(win, "(prefers-contrast: custom)")) return "custom";
|
|
910
|
+
return "no-preference";
|
|
911
|
+
}
|
|
912
|
+
function matchDisplayMode(win) {
|
|
913
|
+
if (!win?.matchMedia) return void 0;
|
|
914
|
+
if (matchMedia(win, "(display-mode: fullscreen)")) return "fullscreen";
|
|
915
|
+
if (matchMedia(win, "(display-mode: standalone)")) return "standalone";
|
|
916
|
+
if (matchMedia(win, "(display-mode: minimal-ui)")) return "minimal-ui";
|
|
917
|
+
if (matchMedia(win, "(display-mode: browser)")) return "browser";
|
|
918
|
+
return void 0;
|
|
919
|
+
}
|
|
920
|
+
function readBuildIdMeta(doc) {
|
|
921
|
+
if (!doc) return void 0;
|
|
922
|
+
const el = doc.querySelector?.('meta[name="mushi:build"]');
|
|
923
|
+
const v = el?.content?.trim();
|
|
924
|
+
if (!v) return void 0;
|
|
925
|
+
return v.slice(0, 64);
|
|
926
|
+
}
|
|
927
|
+
function capturePageLoadTiming(win) {
|
|
928
|
+
const perf = win?.performance;
|
|
929
|
+
if (!perf?.getEntriesByType) return void 0;
|
|
930
|
+
let entry;
|
|
931
|
+
try {
|
|
932
|
+
const entries = perf.getEntriesByType("navigation");
|
|
933
|
+
entry = entries[0];
|
|
934
|
+
} catch {
|
|
935
|
+
return void 0;
|
|
936
|
+
}
|
|
937
|
+
if (!entry) return void 0;
|
|
938
|
+
const start = entry.startTime ?? 0;
|
|
939
|
+
const out = {};
|
|
940
|
+
if (entry.domContentLoadedEventEnd > 0)
|
|
941
|
+
out.domContentLoadedMs = Math.round(entry.domContentLoadedEventEnd - start);
|
|
942
|
+
if (entry.loadEventEnd > 0) out.loadCompleteMs = Math.round(entry.loadEventEnd - start);
|
|
943
|
+
if (entry.responseStart > 0) out.timeToFirstByteMs = Math.round(entry.responseStart - start);
|
|
944
|
+
if (typeof entry.type === "string") out.navigationType = entry.type;
|
|
945
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
946
|
+
}
|
|
799
947
|
|
|
800
948
|
// src/reporter-token.ts
|
|
801
949
|
var STORAGE_KEY = "mushi_reporter_token";
|
|
@@ -1003,6 +1151,75 @@ function scrubPii(text, config) {
|
|
|
1003
1151
|
return createPiiScrubber(config).scrub(text);
|
|
1004
1152
|
}
|
|
1005
1153
|
|
|
1006
|
-
|
|
1154
|
+
// src/breadcrumbs.ts
|
|
1155
|
+
var DEFAULT_MAX = 50;
|
|
1156
|
+
var DEFAULT_MAX_MESSAGE = 500;
|
|
1157
|
+
function createBreadcrumbBuffer(options = {}) {
|
|
1158
|
+
const max = Math.max(1, options.max ?? DEFAULT_MAX);
|
|
1159
|
+
const maxMsg = Math.max(50, options.maxMessageLength ?? DEFAULT_MAX_MESSAGE);
|
|
1160
|
+
let entries = [];
|
|
1161
|
+
return {
|
|
1162
|
+
add(input) {
|
|
1163
|
+
const ts = typeof input.timestamp === "number" ? input.timestamp : Date.now();
|
|
1164
|
+
const message = typeof input.message === "string" && input.message.length > maxMsg ? `${input.message.slice(0, maxMsg)}\u2026` : input.message;
|
|
1165
|
+
const crumb = {
|
|
1166
|
+
timestamp: ts,
|
|
1167
|
+
category: input.category,
|
|
1168
|
+
level: input.level ?? "info",
|
|
1169
|
+
message: message ?? "",
|
|
1170
|
+
...input.data ? { data: input.data } : {}
|
|
1171
|
+
};
|
|
1172
|
+
entries.push(crumb);
|
|
1173
|
+
while (entries.length > max) entries.shift();
|
|
1174
|
+
},
|
|
1175
|
+
getAll() {
|
|
1176
|
+
return entries.slice();
|
|
1177
|
+
},
|
|
1178
|
+
clear() {
|
|
1179
|
+
entries = [];
|
|
1180
|
+
},
|
|
1181
|
+
size() {
|
|
1182
|
+
return entries.length;
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// src/exception-normaliser.ts
|
|
1188
|
+
var STACK_LIMIT = 8 * 1024;
|
|
1189
|
+
var FALLBACK_JSON_LIMIT = 1e3;
|
|
1190
|
+
function normaliseThrown(thrown) {
|
|
1191
|
+
if (thrown instanceof Error) {
|
|
1192
|
+
const name = thrown.name || "Error";
|
|
1193
|
+
const message = thrown.message || String(thrown);
|
|
1194
|
+
const stack = typeof thrown.stack === "string" && thrown.stack.length > 0 ? thrown.stack.slice(0, STACK_LIMIT) : void 0;
|
|
1195
|
+
const cause = thrown.cause;
|
|
1196
|
+
return {
|
|
1197
|
+
name,
|
|
1198
|
+
message,
|
|
1199
|
+
...stack ? { stack } : {},
|
|
1200
|
+
...cause !== void 0 ? { cause: cause instanceof Error ? cause.message : cause } : {}
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
if (typeof thrown === "string") {
|
|
1204
|
+
return { name: "Error", message: thrown };
|
|
1205
|
+
}
|
|
1206
|
+
if (thrown && typeof thrown === "object") {
|
|
1207
|
+
const obj = thrown;
|
|
1208
|
+
const name = typeof obj.name === "string" ? obj.name : "Error";
|
|
1209
|
+
const message = typeof obj.message === "string" ? obj.message : (() => {
|
|
1210
|
+
try {
|
|
1211
|
+
return JSON.stringify(obj).slice(0, FALLBACK_JSON_LIMIT);
|
|
1212
|
+
} catch {
|
|
1213
|
+
return String(obj);
|
|
1214
|
+
}
|
|
1215
|
+
})();
|
|
1216
|
+
const stack = typeof obj.stack === "string" ? obj.stack.slice(0, STACK_LIMIT) : void 0;
|
|
1217
|
+
return { name, message, ...stack ? { stack } : {} };
|
|
1218
|
+
}
|
|
1219
|
+
if (thrown === void 0) return { name: "Error", message: "unknown" };
|
|
1220
|
+
return { name: "Error", message: String(thrown) };
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
export { DEFAULT_API_ENDPOINT, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, REGION_ENDPOINTS, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
|
|
1007
1224
|
//# sourceMappingURL=index.js.map
|
|
1008
1225
|
//# sourceMappingURL=index.js.map
|