@guidelytech/shared 0.2.1 → 0.4.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/{chunk-OFBIZEM5.js → chunk-QUKMOTT4.js} +159 -4
- package/dist/chunk-QUKMOTT4.js.map +1 -0
- package/dist/index.cjs +267 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +352 -83
- package/dist/index.d.ts +352 -83
- package/dist/index.js +124 -7
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +181 -4
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +191 -2
- package/dist/runtime.d.ts +191 -2
- package/dist/runtime.js +47 -3
- package/package.json +1 -1
- package/dist/chunk-OFBIZEM5.js.map +0 -1
|
@@ -67,6 +67,78 @@ function safeRegExp(source, flags = "i") {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
// src/platform.ts
|
|
71
|
+
var PLATFORMS = ["web", "ios", "android"];
|
|
72
|
+
var DEFAULT_PLATFORMS = ["web"];
|
|
73
|
+
function guidePlatforms(config) {
|
|
74
|
+
return Array.isArray(config.platforms) ? [...config.platforms] : [...DEFAULT_PLATFORMS];
|
|
75
|
+
}
|
|
76
|
+
function supportsPlatform(config, platform) {
|
|
77
|
+
return guidePlatforms(config).includes(platform);
|
|
78
|
+
}
|
|
79
|
+
var GUIDELY_ID_ATTRIBUTE = "data-guidely-id";
|
|
80
|
+
function guidelyIdFromSelector(value) {
|
|
81
|
+
const v = (value ?? "").trim();
|
|
82
|
+
if (!v) return null;
|
|
83
|
+
if (/^[A-Za-z0-9_][A-Za-z0-9_\-:.]*$/.test(v)) return v;
|
|
84
|
+
const hash = v.match(/^#([A-Za-z0-9_][A-Za-z0-9_\-:.]*)$/);
|
|
85
|
+
if (hash) return hash[1];
|
|
86
|
+
const attr = v.match(/^(?:[a-z][a-z0-9]*)?\[\s*data-(?:guidely-id|testid|tour)\s*=\s*(["']?)([^"'\]]+)\1\s*\]$/i);
|
|
87
|
+
if (attr) return attr[2].trim();
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function screenPath(screen) {
|
|
91
|
+
const s = (screen ?? "").trim();
|
|
92
|
+
if (!s) return "/";
|
|
93
|
+
return s.startsWith("/") ? s : `/${s}`;
|
|
94
|
+
}
|
|
95
|
+
function compareVersions(a, b) {
|
|
96
|
+
const sa = a == null ? "" : String(a).trim().replace(/^v/i, "");
|
|
97
|
+
const sb = b == null ? "" : String(b).trim().replace(/^v/i, "");
|
|
98
|
+
if (!sa || !sb) return null;
|
|
99
|
+
const pa = sa.split(/[.+-]/);
|
|
100
|
+
const pb = sb.split(/[.+-]/);
|
|
101
|
+
const n = Math.max(pa.length, pb.length);
|
|
102
|
+
for (let i = 0; i < n; i++) {
|
|
103
|
+
const x = pa[i] ?? "0";
|
|
104
|
+
const y = pb[i] ?? "0";
|
|
105
|
+
const nx = /^\d+$/.test(x) ? Number(x) : NaN;
|
|
106
|
+
const ny = /^\d+$/.test(y) ? Number(y) : NaN;
|
|
107
|
+
if (!Number.isNaN(nx) && !Number.isNaN(ny)) {
|
|
108
|
+
if (nx !== ny) return nx < ny ? -1 : 1;
|
|
109
|
+
} else if (x !== y) {
|
|
110
|
+
return x < y ? -1 : 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/widgets.ts
|
|
117
|
+
function isQuestionVisible(q, answers) {
|
|
118
|
+
if (!q.showWhen) return true;
|
|
119
|
+
const actual = answers[q.showWhen.questionId];
|
|
120
|
+
if (actual === void 0) return false;
|
|
121
|
+
const expected = q.showWhen.value;
|
|
122
|
+
switch (q.showWhen.op) {
|
|
123
|
+
case "equals":
|
|
124
|
+
return Array.isArray(actual) ? actual.includes(String(expected)) : String(actual) === String(expected);
|
|
125
|
+
case "lte":
|
|
126
|
+
return Number(actual) <= Number(expected);
|
|
127
|
+
case "gte":
|
|
128
|
+
return Number(actual) >= Number(expected);
|
|
129
|
+
case "in": {
|
|
130
|
+
const list = Array.isArray(expected) ? expected : [String(expected)];
|
|
131
|
+
return Array.isArray(actual) ? actual.some((a) => list.includes(a)) : list.includes(String(actual));
|
|
132
|
+
}
|
|
133
|
+
default:
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function isChecklistComplete(config, progress) {
|
|
138
|
+
const done = new Set(progress.completedTaskIds);
|
|
139
|
+
return config.tasks.filter((t) => t.required).every((t) => done.has(t.id));
|
|
140
|
+
}
|
|
141
|
+
|
|
70
142
|
// src/targeting-eval.ts
|
|
71
143
|
var RULE_OPERATORS = [
|
|
72
144
|
"equals",
|
|
@@ -113,7 +185,10 @@ var RULE_FIELDS = [
|
|
|
113
185
|
"datetime.hour",
|
|
114
186
|
"rollout.percentage",
|
|
115
187
|
"environment",
|
|
116
|
-
"locale"
|
|
188
|
+
"locale",
|
|
189
|
+
"app.platform",
|
|
190
|
+
"app.screen",
|
|
191
|
+
"app.version"
|
|
117
192
|
];
|
|
118
193
|
function isRuleGroup(r) {
|
|
119
194
|
return r.rules !== void 0;
|
|
@@ -175,6 +250,12 @@ function resolveField(rule, ctx) {
|
|
|
175
250
|
return ctx.environment;
|
|
176
251
|
case "locale":
|
|
177
252
|
return ctx.locale;
|
|
253
|
+
case "app.platform":
|
|
254
|
+
return ctx.platform ?? "web";
|
|
255
|
+
case "app.screen":
|
|
256
|
+
return ctx.screen;
|
|
257
|
+
case "app.version":
|
|
258
|
+
return ctx.appVersion;
|
|
178
259
|
default:
|
|
179
260
|
return void 0;
|
|
180
261
|
}
|
|
@@ -254,11 +335,15 @@ function compare(op, actual, expected) {
|
|
|
254
335
|
}
|
|
255
336
|
function evaluateRule(rule, ctx) {
|
|
256
337
|
let result;
|
|
257
|
-
if (rule.field === "url.path" || rule.field === "url.full") {
|
|
338
|
+
if (rule.field === "url.path" || rule.field === "url.full" || rule.field === "app.screen") {
|
|
258
339
|
const actual = String(resolveField(rule, ctx) ?? "");
|
|
259
340
|
if (rule.op === "equals") result = matchUrlPattern(String(rule.value ?? ""), actual);
|
|
260
341
|
else if (rule.op === "not_equals") result = !matchUrlPattern(String(rule.value ?? ""), actual);
|
|
261
342
|
else result = compare(rule.op, actual, rule.value);
|
|
343
|
+
} else if (rule.field === "app.version" && ["equals", "not_equals", "gt", "gte", "lt", "lte"].includes(rule.op)) {
|
|
344
|
+
const c = compareVersions(resolveField(rule, ctx), rule.value);
|
|
345
|
+
if (c === null) result = rule.op === "not_equals";
|
|
346
|
+
else result = rule.op === "equals" ? c === 0 : rule.op === "not_equals" ? c !== 0 : rule.op === "gt" ? c > 0 : rule.op === "gte" ? c >= 0 : rule.op === "lt" ? c < 0 : c <= 0;
|
|
262
347
|
} else {
|
|
263
348
|
result = compare(rule.op, resolveField(rule, ctx), rule.value);
|
|
264
349
|
}
|
|
@@ -295,6 +380,54 @@ function sanitizeProperties(props) {
|
|
|
295
380
|
return out;
|
|
296
381
|
}
|
|
297
382
|
|
|
383
|
+
// src/errors.ts
|
|
384
|
+
var MAX_STACK_FRAMES = 30;
|
|
385
|
+
var V8 = /^\s*at (?:(.+?) \()?((?:[a-z][\w+.-]*:)?[^\s()]+?):(\d+):(\d+)\)?\s*$/i;
|
|
386
|
+
var GECKO = /^\s*(.*?)@(.+?):(\d+):(\d+)\s*$/;
|
|
387
|
+
function parseStack(stack, max = MAX_STACK_FRAMES) {
|
|
388
|
+
if (!stack || typeof stack !== "string") return [];
|
|
389
|
+
const frames = [];
|
|
390
|
+
for (const raw of stack.split("\n")) {
|
|
391
|
+
if (frames.length >= max) break;
|
|
392
|
+
const line = raw.slice(0, 1e3);
|
|
393
|
+
const m = V8.exec(line) ?? GECKO.exec(line);
|
|
394
|
+
if (!m) continue;
|
|
395
|
+
const fn = (m[1] || "").trim();
|
|
396
|
+
frames.push({ fn: fn ? fn.slice(0, 200) : void 0, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });
|
|
397
|
+
}
|
|
398
|
+
return frames;
|
|
399
|
+
}
|
|
400
|
+
function normalizeErrorMessage(message) {
|
|
401
|
+
return (message || "").slice(0, 500).replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "<uuid>").replace(/(["'`]).*?\1/g, "<str>").replace(/\b0x[0-9a-f]+\b/gi, "<hex>").replace(/\d+(\.\d+)?/g, "<n>").replace(/\s+/g, " ").trim();
|
|
402
|
+
}
|
|
403
|
+
function normalizeFrameFile(file) {
|
|
404
|
+
if (!file) return "";
|
|
405
|
+
let path = file;
|
|
406
|
+
try {
|
|
407
|
+
path = new URL(file).pathname;
|
|
408
|
+
} catch {
|
|
409
|
+
path = file.replace(/[?#].*$/, "");
|
|
410
|
+
}
|
|
411
|
+
return path.replace(/[.-][0-9a-f]{6,}(?=\.\w+$)/i, "").replace(/\/\d+\//g, "/<n>/");
|
|
412
|
+
}
|
|
413
|
+
var SOURCEMAP_MAX_FILE_BYTES = 25 * 1024 * 1024;
|
|
414
|
+
var SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;
|
|
415
|
+
function fingerprintError(input) {
|
|
416
|
+
const top = (input.frames ?? []).find((f) => f.file);
|
|
417
|
+
const frameKey = input.original ? `src:${input.original.source}:${input.original.name || "?"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || "?"}` : "";
|
|
418
|
+
const key = [input.type || "Error", normalizeErrorMessage(input.message || ""), frameKey].join("|");
|
|
419
|
+
const a = fnv1a(key).toString(16).padStart(8, "0");
|
|
420
|
+
const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, "0");
|
|
421
|
+
return a + b;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// src/network.ts
|
|
425
|
+
var NETWORK_PLUGIN = "guidely/network@1";
|
|
426
|
+
var WS_MAX_MESSAGES_PER_SOCKET = 200;
|
|
427
|
+
var WS_MAX_MESSAGE_BYTES = 2048;
|
|
428
|
+
var SENSITIVE_HEADER_PATTERN = /^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|x-csrf-token|x-xsrf-token|x-guidely-key|x-guidely-conversation)$/i;
|
|
429
|
+
var SENSITIVE_PARAM_PATTERN = /(token|key|secret|password|passwd|pwd|auth|session|code|sig|signature|credential|ssn|card|cvv|iban)/i;
|
|
430
|
+
|
|
298
431
|
export {
|
|
299
432
|
fnv1a,
|
|
300
433
|
rolloutBucket,
|
|
@@ -306,6 +439,16 @@ export {
|
|
|
306
439
|
matchUrlPattern,
|
|
307
440
|
stripOrigin,
|
|
308
441
|
safeRegExp,
|
|
442
|
+
PLATFORMS,
|
|
443
|
+
DEFAULT_PLATFORMS,
|
|
444
|
+
guidePlatforms,
|
|
445
|
+
supportsPlatform,
|
|
446
|
+
GUIDELY_ID_ATTRIBUTE,
|
|
447
|
+
guidelyIdFromSelector,
|
|
448
|
+
screenPath,
|
|
449
|
+
compareVersions,
|
|
450
|
+
isQuestionVisible,
|
|
451
|
+
isChecklistComplete,
|
|
309
452
|
RULE_OPERATORS,
|
|
310
453
|
RULE_FIELDS,
|
|
311
454
|
isRuleGroup,
|
|
@@ -317,6 +460,18 @@ export {
|
|
|
317
460
|
describeRule,
|
|
318
461
|
SENSITIVE_PROPERTY_PATTERN,
|
|
319
462
|
MAX_PROPERTY_BYTES,
|
|
320
|
-
sanitizeProperties
|
|
463
|
+
sanitizeProperties,
|
|
464
|
+
MAX_STACK_FRAMES,
|
|
465
|
+
parseStack,
|
|
466
|
+
normalizeErrorMessage,
|
|
467
|
+
normalizeFrameFile,
|
|
468
|
+
SOURCEMAP_MAX_FILE_BYTES,
|
|
469
|
+
SOURCEMAP_MAX_FILES_PER_UPLOAD,
|
|
470
|
+
fingerprintError,
|
|
471
|
+
NETWORK_PLUGIN,
|
|
472
|
+
WS_MAX_MESSAGES_PER_SOCKET,
|
|
473
|
+
WS_MAX_MESSAGE_BYTES,
|
|
474
|
+
SENSITIVE_HEADER_PATTERN,
|
|
475
|
+
SENSITIVE_PARAM_PATTERN
|
|
321
476
|
};
|
|
322
|
-
//# sourceMappingURL=chunk-
|
|
477
|
+
//# sourceMappingURL=chunk-QUKMOTT4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/platform.ts","../src/widgets.ts","../src/targeting-eval.ts","../src/events-util.ts","../src/errors.ts","../src/network.ts"],"sourcesContent":["/** FNV-1a 32-bit hash; deterministic across SDK and server for rollout bucketing. */\nexport function fnv1a(input: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h >>> 0;\n}\n\n/** Deterministic 0-99 bucket for percentage rollouts. */\nexport function rolloutBucket(subject: string, salt: string): number {\n return fnv1a(`${salt}:${subject}`) % 100;\n}\n\nexport function slugify(input: string): string {\n return input\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64) || \"untitled\";\n}\n\nconst ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n/** URL-safe random id. Uses crypto when available, falls back to Math.random (ids are not secrets). */\nexport function randomId(size = 16): string {\n const g: any = typeof globalThis !== \"undefined\" ? globalThis : {};\n let bytes: Uint8Array;\n if (g.crypto && typeof g.crypto.getRandomValues === \"function\") {\n bytes = new Uint8Array(size);\n g.crypto.getRandomValues(bytes);\n } else {\n bytes = new Uint8Array(size);\n for (let i = 0; i < size; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n let out = \"\";\n for (let i = 0; i < size; i++) out += ALPHABET[(bytes[i] as number) % ALPHABET.length];\n return out;\n}\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Safe nested getter: get(obj, \"account.plan\") */\nexport function getPath(obj: unknown, path: string): unknown {\n if (!path) return obj;\n let cur: any = obj;\n for (const part of path.split(\".\")) {\n if (cur == null) return undefined;\n cur = cur[part];\n }\n return cur;\n}\n\nexport function clamp(n: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, n));\n}\n\n/** Glob-style URL pattern match: `*` matches any chars except `/`, `**` matches anything. */\nexport function matchUrlPattern(pattern: string, url: string): boolean {\n if (!pattern) return true;\n if (pattern === url) return true;\n const escaped = pattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"__GLOBSTAR__\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/__GLOBSTAR__/g, \".*\");\n const re = new RegExp(`^${escaped}$`);\n return re.test(url) || re.test(stripOrigin(url));\n}\n\nexport function stripOrigin(url: string): string {\n try {\n const u = new URL(url);\n return u.pathname + u.search + u.hash;\n } catch {\n return url;\n }\n}\n\n/** Safe regexp construction with a length cap to limit ReDoS exposure. */\nexport function safeRegExp(source: string, flags = \"i\"): RegExp | null {\n if (!source || source.length > 200) return null;\n try {\n return new RegExp(source, flags);\n } catch {\n return null;\n }\n}\n","/**\n * Cross-platform helpers shared by the web SDK, the React Native SDK and (as a reference for) the\n * native iOS/Android SDKs. Zod-free so it can ship in runtime bundles.\n */\n\n/** Platforms a guide can be delivered to. */\nexport const PLATFORMS = [\"web\", \"ios\", \"android\"] as const;\nexport type Platform = (typeof PLATFORMS)[number];\n\n/** Guides published before platforms existed have no `platforms` field and are web-only. */\nexport const DEFAULT_PLATFORMS: Platform[] = [\"web\"];\n\n/** Platforms a guide config targets (missing field → web only). */\nexport function guidePlatforms(config: { platforms?: readonly string[] | null }): string[] {\n return Array.isArray(config.platforms) ? [...config.platforms] : [...DEFAULT_PLATFORMS];\n}\n\nexport function supportsPlatform(config: { platforms?: readonly string[] | null }, platform: string): boolean {\n return guidePlatforms(config).includes(platform);\n}\n\n/** Attribute web apps put on elements to share a target id with their mobile apps. */\nexport const GUIDELY_ID_ATTRIBUTE = \"data-guidely-id\";\n\n/**\n * Extracts a Guidely target id from a trigger / advance / checklist value so the same guide works on\n * web and mobile. Accepts a bare id (`new-deal`), `#new-deal`, or `[data-guidely-id=\"new-deal\"]`\n * (also `data-testid` / `data-tour`). Returns null for selectors that cannot name a single id.\n */\nexport function guidelyIdFromSelector(value: string | null | undefined): string | null {\n const v = (value ?? \"\").trim();\n if (!v) return null;\n if (/^[A-Za-z0-9_][A-Za-z0-9_\\-:.]*$/.test(v)) return v;\n const hash = v.match(/^#([A-Za-z0-9_][A-Za-z0-9_\\-:.]*)$/);\n if (hash) return hash[1] as string;\n const attr = v.match(/^(?:[a-z][a-z0-9]*)?\\[\\s*data-(?:guidely-id|testid|tour)\\s*=\\s*([\"']?)([^\"'\\]]+)\\1\\s*\\]$/i);\n if (attr) return (attr[2] as string).trim();\n return null;\n}\n\n/**\n * Mobile SDKs have screens instead of URLs. URL-based features (URL patterns, `url_match` triggers,\n * multi-page steps, `url_visited` checklist tasks) match against the screen path `/<ScreenName>`.\n */\nexport function screenPath(screen: string | null | undefined): string {\n const s = (screen ?? \"\").trim();\n if (!s) return \"/\";\n return s.startsWith(\"/\") ? s : `/${s}`;\n}\n\n/**\n * Compares dotted version strings numerically (`2.10.0` > `2.9.3`). Non-numeric parts compare as\n * strings; a missing part counts as 0 (`2.1` == `2.1.0`). Returns -1, 0 or 1, or null when either\n * side is empty.\n */\nexport function compareVersions(a: unknown, b: unknown): -1 | 0 | 1 | null {\n const sa = a == null ? \"\" : String(a).trim().replace(/^v/i, \"\");\n const sb = b == null ? \"\" : String(b).trim().replace(/^v/i, \"\");\n if (!sa || !sb) return null;\n const pa = sa.split(/[.+-]/);\n const pb = sb.split(/[.+-]/);\n const n = Math.max(pa.length, pb.length);\n for (let i = 0; i < n; i++) {\n const x = pa[i] ?? \"0\";\n const y = pb[i] ?? \"0\";\n const nx = /^\\d+$/.test(x) ? Number(x) : NaN;\n const ny = /^\\d+$/.test(y) ? Number(y) : NaN;\n if (!Number.isNaN(nx) && !Number.isNaN(ny)) {\n if (nx !== ny) return nx < ny ? -1 : 1;\n } else if (x !== y) {\n return x < y ? -1 : 1;\n }\n }\n return 0;\n}\n","/**\n * Pure checklist / survey logic shared by every renderer (web runtime, React Native, and the\n * reference for the native SDKs). Zod-free; uses structural types so it stays in the runtime entry.\n */\n\nexport type SurveyAnswer = string | number | boolean | string[];\nexport type SurveyAnswers = Record<string, SurveyAnswer>;\n\nexport interface ShowWhen {\n questionId: string;\n op: \"equals\" | \"lte\" | \"gte\" | \"in\";\n value: string | number | string[];\n}\n\n/** Evaluates a question's `showWhen` condition against current answers. */\nexport function isQuestionVisible(q: { showWhen?: ShowWhen }, answers: SurveyAnswers): boolean {\n if (!q.showWhen) return true;\n const actual = answers[q.showWhen.questionId];\n if (actual === undefined) return false;\n const expected = q.showWhen.value;\n switch (q.showWhen.op) {\n case \"equals\":\n return Array.isArray(actual) ? actual.includes(String(expected)) : String(actual) === String(expected);\n case \"lte\":\n return Number(actual) <= Number(expected);\n case \"gte\":\n return Number(actual) >= Number(expected);\n case \"in\": {\n const list = Array.isArray(expected) ? expected : [String(expected)];\n return Array.isArray(actual) ? actual.some((a) => list.includes(a)) : list.includes(String(actual));\n }\n default:\n return false;\n }\n}\n\n/** Are all required tasks done? */\nexport function isChecklistComplete(config: { tasks: Array<{ id: string; required: boolean }> }, progress: { completedTaskIds: string[] }): boolean {\n const done = new Set(progress.completedTaskIds);\n return config.tasks.filter((t) => t.required).every((t) => done.has(t.id));\n}\n","/**\n * Zod-free targeting evaluation. Imported by the browser SDK via `@guidelytech/shared/runtime`\n * so the runtime bundle does not pull in zod. Schemas live in ./targeting.ts.\n */\nimport { compareVersions } from \"./platform\";\nimport { getPath, matchUrlPattern, rolloutBucket, safeRegExp } from \"./utils\";\n\nexport const RULE_OPERATORS = [\n \"equals\",\n \"not_equals\",\n \"contains\",\n \"not_contains\",\n \"starts_with\",\n \"ends_with\",\n \"exists\",\n \"not_exists\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"in\",\n \"not_in\",\n \"regex\",\n \"is_true\",\n \"is_false\",\n \"before\",\n \"after\",\n] as const;\nexport type RuleOperator = (typeof RULE_OPERATORS)[number];\n\nexport const RULE_FIELDS = [\n \"user.attribute\",\n \"account.attribute\",\n \"user.role\",\n \"user.plan\",\n \"url.path\",\n \"url.full\",\n \"url.query\",\n \"device.type\",\n \"device.browser\",\n \"device.os\",\n \"visitor.firstVisit\",\n \"visitor.returning\",\n \"event.seen\",\n \"guide.completed\",\n \"guide.dismissed\",\n \"guide.seen\",\n \"checklist.completed\",\n \"audience.member\",\n \"datetime.now\",\n \"datetime.dayOfWeek\",\n \"datetime.hour\",\n \"rollout.percentage\",\n \"environment\",\n \"locale\",\n \"app.platform\",\n \"app.screen\",\n \"app.version\",\n] as const;\nexport type RuleField = (typeof RULE_FIELDS)[number];\n\nexport interface Rule {\n id: string;\n field: RuleField;\n /** For attribute/query/event fields: the attribute key, query param name, event name, guide id... */\n key?: string;\n op: RuleOperator;\n value?: string | number | boolean | string[];\n /** When true, the rule is negated (exclusion rule). */\n negate?: boolean;\n}\n\nexport type RuleGroup = {\n id: string;\n op: \"and\" | \"or\";\n rules: Array<Rule | RuleGroup>;\n negate?: boolean;\n};\n\nexport function isRuleGroup(r: Rule | RuleGroup): r is RuleGroup {\n return (r as RuleGroup).rules !== undefined;\n}\n\nexport function emptyRuleGroup(id = \"root\"): RuleGroup {\n return { id, op: \"and\", rules: [] };\n}\n\n/** Everything targeting evaluation can see. Built by the SDK (browser) or the server. */\nexport interface TargetingContext {\n userId?: string | null;\n anonymousId: string;\n userAttributes: Record<string, unknown>;\n accountAttributes: Record<string, unknown>;\n url: string;\n path: string;\n query: Record<string, string>;\n device: { type: \"desktop\" | \"tablet\" | \"mobile\"; browser?: string; os?: string };\n firstVisit: boolean;\n eventsSeen: Set<string> | string[];\n completedGuides: Set<string> | string[];\n dismissedGuides: Set<string> | string[];\n seenGuides: Set<string> | string[];\n completedChecklists: Set<string> | string[];\n audienceIds: Set<string> | string[];\n now: Date;\n environment: string;\n locale?: string;\n /** `web`, `ios` or `android`. Missing means web. */\n platform?: string;\n /** Current screen name (mobile SDKs; set via `screen()`). */\n screen?: string;\n /** Host app version (mobile SDKs), e.g. `2.4.1`. */\n appVersion?: string;\n /** Salt for rollout (guide id). Set per guide before evaluating. */\n rolloutSalt?: string;\n}\n\nfunction has(set: Set<string> | string[] | undefined, v: string): boolean {\n if (!set) return false;\n return set instanceof Set ? set.has(v) : set.includes(v);\n}\n\nfunction resolveField(rule: Rule, ctx: TargetingContext): unknown {\n switch (rule.field) {\n case \"user.attribute\":\n return rule.key ? getPath(ctx.userAttributes, rule.key) : undefined;\n case \"account.attribute\":\n return rule.key ? getPath(ctx.accountAttributes, rule.key) : undefined;\n case \"user.role\":\n return ctx.userAttributes.role;\n case \"user.plan\":\n return ctx.userAttributes.plan ?? ctx.accountAttributes.plan;\n case \"url.path\":\n return ctx.path;\n case \"url.full\":\n return ctx.url;\n case \"url.query\":\n return rule.key ? ctx.query[rule.key] : undefined;\n case \"device.type\":\n return ctx.device.type;\n case \"device.browser\":\n return ctx.device.browser;\n case \"device.os\":\n return ctx.device.os;\n case \"visitor.firstVisit\":\n return ctx.firstVisit;\n case \"visitor.returning\":\n return !ctx.firstVisit;\n case \"event.seen\":\n return rule.key ? has(ctx.eventsSeen, rule.key) : false;\n case \"guide.completed\":\n return rule.key ? has(ctx.completedGuides, rule.key) : false;\n case \"guide.dismissed\":\n return rule.key ? has(ctx.dismissedGuides, rule.key) : false;\n case \"guide.seen\":\n return rule.key ? has(ctx.seenGuides, rule.key) : false;\n case \"checklist.completed\":\n return rule.key ? has(ctx.completedChecklists, rule.key) : false;\n case \"audience.member\":\n return rule.key ? has(ctx.audienceIds, rule.key) : false;\n case \"datetime.now\":\n return ctx.now.toISOString();\n case \"datetime.dayOfWeek\":\n return ctx.now.getDay();\n case \"datetime.hour\":\n return ctx.now.getHours();\n case \"rollout.percentage\":\n return rolloutBucket(ctx.userId || ctx.anonymousId, ctx.rolloutSalt || \"guidely\");\n case \"environment\":\n return ctx.environment;\n case \"locale\":\n return ctx.locale;\n case \"app.platform\":\n return ctx.platform ?? \"web\";\n case \"app.screen\":\n return ctx.screen;\n case \"app.version\":\n return ctx.appVersion;\n default:\n return undefined;\n }\n}\n\nfunction toNumber(v: unknown): number | null {\n if (typeof v === \"number\") return v;\n if (typeof v === \"string\" && v.trim() !== \"\" && !Number.isNaN(Number(v))) return Number(v);\n if (v instanceof Date) return v.getTime();\n return null;\n}\n\nfunction toDateMs(v: unknown): number | null {\n if (v instanceof Date) return v.getTime();\n if (typeof v === \"string\") {\n const t = Date.parse(v);\n return Number.isNaN(t) ? null : t;\n }\n if (typeof v === \"number\") return v;\n return null;\n}\n\nexport function compare(op: RuleOperator, actual: unknown, expected: Rule[\"value\"]): boolean {\n switch (op) {\n case \"exists\":\n return actual !== undefined && actual !== null && actual !== \"\";\n case \"not_exists\":\n return actual === undefined || actual === null || actual === \"\";\n case \"is_true\":\n return actual === true || actual === \"true\";\n case \"is_false\":\n return actual === false || actual === \"false\";\n case \"equals\":\n if (typeof actual === \"boolean\") return String(actual) === String(expected);\n return String(actual ?? \"\") === String(expected ?? \"\");\n case \"not_equals\":\n return String(actual ?? \"\") !== String(expected ?? \"\");\n case \"contains\":\n return typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase());\n case \"not_contains\":\n return !(typeof actual === \"string\" && actual.toLowerCase().includes(String(expected ?? \"\").toLowerCase()));\n case \"starts_with\":\n return typeof actual === \"string\" && actual.startsWith(String(expected ?? \"\"));\n case \"ends_with\":\n return typeof actual === \"string\" && actual.endsWith(String(expected ?? \"\"));\n case \"gt\":\n case \"gte\":\n case \"lt\":\n case \"lte\": {\n const a = toNumber(actual);\n const b = toNumber(expected);\n if (a === null || b === null) return false;\n return op === \"gt\" ? a > b : op === \"gte\" ? a >= b : op === \"lt\" ? a < b : a <= b;\n }\n case \"in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return list.includes(String(actual ?? \"\"));\n }\n case \"not_in\": {\n const list = Array.isArray(expected) ? expected : String(expected ?? \"\").split(\",\").map((s) => s.trim());\n return !list.includes(String(actual ?? \"\"));\n }\n case \"regex\": {\n const re = safeRegExp(String(expected ?? \"\"));\n return !!re && typeof actual === \"string\" && re.test(actual);\n }\n case \"before\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a < b;\n }\n case \"after\": {\n const a = toDateMs(actual);\n const b = toDateMs(expected);\n return a !== null && b !== null && a > b;\n }\n default:\n return false;\n }\n}\n\nexport function evaluateRule(rule: Rule, ctx: TargetingContext): boolean {\n let result: boolean;\n if (rule.field === \"url.path\" || rule.field === \"url.full\" || rule.field === \"app.screen\") {\n const actual = String(resolveField(rule, ctx) ?? \"\");\n if (rule.op === \"equals\") result = matchUrlPattern(String(rule.value ?? \"\"), actual);\n else if (rule.op === \"not_equals\") result = !matchUrlPattern(String(rule.value ?? \"\"), actual);\n else result = compare(rule.op, actual, rule.value);\n } else if (rule.field === \"app.version\" && [\"equals\", \"not_equals\", \"gt\", \"gte\", \"lt\", \"lte\"].includes(rule.op)) {\n const c = compareVersions(resolveField(rule, ctx), rule.value);\n if (c === null) result = rule.op === \"not_equals\";\n else result = rule.op === \"equals\" ? c === 0 : rule.op === \"not_equals\" ? c !== 0 : rule.op === \"gt\" ? c > 0 : rule.op === \"gte\" ? c >= 0 : rule.op === \"lt\" ? c < 0 : c <= 0;\n } else {\n result = compare(rule.op, resolveField(rule, ctx), rule.value);\n }\n return rule.negate ? !result : result;\n}\n\n/** Evaluate a rule tree. An empty group matches everyone. */\nexport function evaluateRules(group: RuleGroup | null | undefined, ctx: TargetingContext): boolean {\n if (!group || group.rules.length === 0) return group?.negate ? false : true;\n const results = group.rules.map((r) => (isRuleGroup(r) ? evaluateRules(r, ctx) : evaluateRule(r, ctx)));\n const value = group.op === \"and\" ? results.every(Boolean) : results.some(Boolean);\n return group.negate ? !value : value;\n}\n\n/** Fields whose evaluation requires server-held data. Used by docs/UI to annotate rules. */\nexport const SERVER_ASSISTED_FIELDS: RuleField[] = [\"audience.member\", \"guide.completed\", \"guide.dismissed\", \"guide.seen\", \"checklist.completed\"];\n\nexport function describeRule(rule: Rule): string {\n const subject = rule.key ? `${rule.field}[${rule.key}]` : rule.field;\n const v = Array.isArray(rule.value) ? rule.value.join(\", \") : rule.value === undefined ? \"\" : String(rule.value);\n return `${rule.negate ? \"NOT \" : \"\"}${subject} ${rule.op.replace(/_/g, \" \")}${v ? ` \"${v}\"` : \"\"}`;\n}\n","/** Reserved property names that are stripped from `properties` to avoid collecting sensitive data. */\nexport const SENSITIVE_PROPERTY_PATTERN = /(password|passwd|secret|token|credit|card|cvv|ssn|iban)/i;\n\nexport const MAX_PROPERTY_BYTES = 8 * 1024;\n\nexport function sanitizeProperties(props: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!props) return {};\n const out: Record<string, unknown> = {};\n let size = 0;\n for (const [k, v] of Object.entries(props)) {\n if (SENSITIVE_PROPERTY_PATTERN.test(k)) continue;\n if (typeof v === \"function\" || typeof v === \"symbol\") continue;\n const str = typeof v === \"string\" ? v : JSON.stringify(v ?? null);\n size += k.length + (str?.length ?? 0);\n if (size > MAX_PROPERTY_BYTES) break;\n out[k.slice(0, 100)] = typeof v === \"string\" ? v.slice(0, 1000) : v;\n }\n return out;\n}\n","import { fnv1a } from \"./utils\";\n\n/** One parsed stack frame. `file` is the script URL (or path) as the browser reported it. */\nexport interface StackFrame {\n fn?: string;\n file?: string;\n line?: number;\n col?: number;\n}\n\n/** Properties carried by an `exception` event (see `docs/product-analytics.md`). */\nexport interface ExceptionProperties {\n type: string;\n message: string;\n frames: StackFrame[];\n /** `onerror` | `unhandledrejection` | `manual` (captureException) | `console`. */\n source?: string;\n handled?: boolean;\n /** App version or commit (SDK option `release`); selects the matching uploaded source maps. */\n release?: string;\n /** Set by the server at ingestion; groups occurrences into an issue. */\n fingerprint?: string;\n}\n\nexport const MAX_STACK_FRAMES = 30;\n\n// Chrome / Edge / Node: \" at fn (https://x/app.js:1:2)\" or \" at https://x/app.js:1:2\"\nconst V8 = /^\\s*at (?:(.+?) \\()?((?:[a-z][\\w+.-]*:)?[^\\s()]+?):(\\d+):(\\d+)\\)?\\s*$/i;\n// Firefox / Safari: \"fn@https://x/app.js:1:2\" or \"@https://x/app.js:1:2\"\nconst GECKO = /^\\s*(.*?)@(.+?):(\\d+):(\\d+)\\s*$/;\n\n/** Parses `Error.stack` from V8, SpiderMonkey and JavaScriptCore into frames (innermost first). */\nexport function parseStack(stack: string | undefined | null, max = MAX_STACK_FRAMES): StackFrame[] {\n if (!stack || typeof stack !== \"string\") return [];\n const frames: StackFrame[] = [];\n for (const raw of stack.split(\"\\n\")) {\n if (frames.length >= max) break;\n const line = raw.slice(0, 1000);\n const m = V8.exec(line) ?? GECKO.exec(line);\n if (!m) continue;\n const fn = (m[1] || \"\").trim();\n frames.push({ fn: fn ? fn.slice(0, 200) : undefined, file: m[2]?.slice(0, 500), line: Number(m[3]), col: Number(m[4]) });\n }\n return frames;\n}\n\n/** Replaces volatile parts of a message (numbers, ids, quoted values) so repeats group together. */\nexport function normalizeErrorMessage(message: string): string {\n return (message || \"\")\n .slice(0, 500)\n .replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, \"<uuid>\")\n .replace(/([\"'`]).*?\\1/g, \"<str>\")\n .replace(/\\b0x[0-9a-f]+\\b/gi, \"<hex>\")\n .replace(/\\d+(\\.\\d+)?/g, \"<n>\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n/** Strips origin, query, hash and build hashes (`main.3f2a1b9c.js` → `main.js`) from a script URL. */\nexport function normalizeFrameFile(file: string | undefined): string {\n if (!file) return \"\";\n let path = file;\n try {\n path = new URL(file).pathname;\n } catch {\n path = file.replace(/[?#].*$/, \"\");\n }\n return path.replace(/[.-][0-9a-f]{6,}(?=\\.\\w+$)/i, \"\").replace(/\\/\\d+\\//g, \"/<n>/\");\n}\n\n/** Source map upload limits (`POST /api/v1/sourcemaps/upload`). */\nexport const SOURCEMAP_MAX_FILE_BYTES = 25 * 1024 * 1024;\nexport const SOURCEMAP_MAX_FILES_PER_UPLOAD = 200;\n\n/**\n * Stable issue key for an exception: error type + normalised message + the innermost frame that\n * has a file (path without build hash + function name, or its original source + name when a source\n * map resolved it). Line/column numbers are left out because they change with every deploy of a\n * minified bundle.\n */\nexport function fingerprintError(input: { type?: string; message?: string; frames?: StackFrame[]; original?: { source: string; name?: string | null } | null }): string {\n const top = (input.frames ?? []).find((f) => f.file);\n // With a source map the original file and function name identify the frame across deploys, even\n // when a minifier renames functions between builds.\n const frameKey = input.original ? `src:${input.original.source}:${input.original.name || \"?\"}` : top ? `${normalizeFrameFile(top.file)}:${top.fn || \"?\"}` : \"\";\n const key = [input.type || \"Error\", normalizeErrorMessage(input.message || \"\"), frameKey].join(\"|\");\n const a = fnv1a(key).toString(16).padStart(8, \"0\");\n const b = fnv1a(`guidely:${key}`).toString(16).padStart(8, \"0\");\n return a + b;\n}\n","/* Network requests recorded into session replays (zod-free: imported by the SDK recorder). */\n\n/** rrweb plugin name for network events in recordings (event type 6, `data.plugin`). */\nexport const NETWORK_PLUGIN = \"guidely/network@1\";\n\n/** Request kinds, from `fetch`/`XMLHttpRequest` patching or `PerformanceResourceTiming.initiatorType`. */\nexport type NetworkRequestType = \"fetch\" | \"xhr\" | \"websocket\" | \"document\" | \"script\" | \"stylesheet\" | \"image\" | \"font\" | \"media\" | \"beacon\" | \"other\";\n\n/**\n * One network request in a recording: the payload of an rrweb plugin event\n * `{ type: 6, data: { plugin: NETWORK_PLUGIN, payload: NetworkPluginPayload } }`, batched.\n * Times are epoch milliseconds (same clock as rrweb event timestamps).\n *\n * A WebSocket is a request with `type: \"websocket\"` and `method: \"GET\"`, emitted when it opens\n * (`startTime`) and again, with the same `id`, when it closes (`endTime`, `closeCode`, `closeReason`,\n * totals in `messages`). Its frames are `WebSocketMessage`s referencing that `id`.\n */\nexport interface NetworkRequest {\n /** Stable id within the recording. */\n id: string;\n type: NetworkRequestType;\n method: string;\n /** Absolute URL; values of sensitive-looking query parameters replaced with `[redacted]`. */\n url: string;\n startTime: number;\n endTime?: number;\n durationMs?: number;\n /** HTTP status; 0 for network errors / blocked / aborted. Absent when the browser doesn't expose it. */\n status?: number;\n /** Set for failed requests: network error, abort or timeout message. */\n error?: string;\n /** Encoded bytes transferred / decoded response size, when known. */\n transferSize?: number;\n responseSize?: number;\n /** Only when `recordNetworkPayloads` is on; sensitive headers are `[redacted]`. */\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n /** Text/JSON bodies, ≤10KB, sensitive JSON fields masked; `[binary]` / `[truncated]` markers otherwise. */\n requestBody?: string;\n responseBody?: string;\n /** WebSocket only: negotiated subprotocol, close details, and frame totals (all frames, including ones not recorded). */\n protocol?: string;\n closeCode?: number;\n closeReason?: string;\n messages?: { sent: number; received: number; sentBytes: number; receivedBytes: number; recorded: number };\n}\n\n/** One WebSocket frame. At most `WS_MAX_MESSAGES_PER_SOCKET` are recorded per connection per page load. */\nexport interface WebSocketMessage {\n /** The `NetworkRequest.id` of the connection. */\n socketId: string;\n dir: \"send\" | \"recv\";\n time: number;\n /** Bytes (UTF-8 length for text frames). */\n size: number;\n binary?: boolean;\n /** Only with `recordNetworkPayloads`: text ≤ 2KB (JSON with sensitive keys masked), else `[truncated]`; binary frames are `[binary <n> B]`. */\n data?: string;\n}\n\nexport interface NetworkPluginPayload {\n requests?: NetworkRequest[];\n messages?: WebSocketMessage[];\n /** Requests/frames dropped since the previous payload because a cap was reached. */\n dropped?: { requests?: number; messages?: number };\n}\n\nexport const WS_MAX_MESSAGES_PER_SOCKET = 200;\nexport const WS_MAX_MESSAGE_BYTES = 2048;\n\n/** Header names always replaced with `[redacted]` when payload capture is on. */\nexport const SENSITIVE_HEADER_PATTERN = /^(authorization|proxy-authorization|cookie|set-cookie|x-api-key|x-auth-token|x-csrf-token|x-xsrf-token|x-guidely-key|x-guidely-conversation)$/i;\n\n/** Query parameter and JSON field names whose values are redacted. */\nexport const SENSITIVE_PARAM_PATTERN = /(token|key|secret|password|passwd|pwd|auth|session|code|sig|signature|credential|ssn|card|cvv|iban)/i;\n"],"mappings":"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","names":[]}
|