@uptimizr/sdk-core 0.1.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/AGENTS.md +70 -0
- package/LICENSE +201 -0
- package/README.md +109 -0
- package/dist/client.d.ts +116 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +451 -0
- package/dist/client.js.map +1 -0
- package/dist/coordinates.d.ts +98 -0
- package/dist/coordinates.d.ts.map +1 -0
- package/dist/coordinates.js +127 -0
- package/dist/coordinates.js.map +1 -0
- package/dist/gesture.d.ts +96 -0
- package/dist/gesture.d.ts.map +1 -0
- package/dist/gesture.js +178 -0
- package/dist/gesture.js.map +1 -0
- package/dist/idgen.d.ts +8 -0
- package/dist/idgen.d.ts.map +1 -0
- package/dist/idgen.js +15 -0
- package/dist/idgen.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/matrix.d.ts +22 -0
- package/dist/matrix.d.ts.map +1 -0
- package/dist/matrix.js +60 -0
- package/dist/matrix.js.map +1 -0
- package/dist/offloadProtocol.d.ts +40 -0
- package/dist/offloadProtocol.d.ts.map +1 -0
- package/dist/offloadProtocol.js +2 -0
- package/dist/offloadProtocol.js.map +1 -0
- package/dist/offloadWorker.d.ts +2 -0
- package/dist/offloadWorker.d.ts.map +1 -0
- package/dist/offloadWorker.js +41 -0
- package/dist/offloadWorker.js.map +1 -0
- package/dist/processor.d.ts +102 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +145 -0
- package/dist/processor.js.map +1 -0
- package/dist/queue.d.ts +22 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +39 -0
- package/dist/queue.js.map +1 -0
- package/dist/sampling.d.ts +124 -0
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +36 -0
- package/dist/sampling.js.map +1 -0
- package/dist/transport.d.ts +10 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +37 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +186 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/xrInput.d.ts +54 -0
- package/dist/xrInput.d.ts.map +1 -0
- package/dist/xrInput.js +20 -0
- package/dist/xrInput.js.map +1 -0
- package/llms.txt +16 -0
- package/package.json +61 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import { SCHEMA_VERSION, DEFAULT_SCENE_ID, sceneIdSchema } from "@uptimizr/schema";
|
|
2
|
+
import { EventQueue } from "./queue.js";
|
|
3
|
+
import { randomId } from "./idgen.js";
|
|
4
|
+
import { createBeaconTransport } from "./transport.js";
|
|
5
|
+
import { createMainProcessor, createWorkerProcessor, } from "./processor.js";
|
|
6
|
+
import { SDK_VERSION } from "./version.js";
|
|
7
|
+
const DEFAULTS = {
|
|
8
|
+
batchSize: 20,
|
|
9
|
+
flushIntervalMs: 5000,
|
|
10
|
+
maxQueueSize: 1000,
|
|
11
|
+
resizeDebounceMs: 250,
|
|
12
|
+
};
|
|
13
|
+
function resolveConfig(config) {
|
|
14
|
+
return {
|
|
15
|
+
projectId: config.projectId,
|
|
16
|
+
endpoint: config.endpoint,
|
|
17
|
+
sdkVersion: config.sdkVersion ?? SDK_VERSION,
|
|
18
|
+
batchSize: config.batchSize ?? DEFAULTS.batchSize,
|
|
19
|
+
flushIntervalMs: config.flushIntervalMs ?? DEFAULTS.flushIntervalMs,
|
|
20
|
+
maxQueueSize: config.maxQueueSize ?? DEFAULTS.maxQueueSize,
|
|
21
|
+
offload: config.offload ?? "main",
|
|
22
|
+
disabled: config.disabled ?? false,
|
|
23
|
+
captureLifecycle: config.captureLifecycle ?? true,
|
|
24
|
+
resizeDebounceMs: config.resizeDebounceMs ?? DEFAULTS.resizeDebounceMs,
|
|
25
|
+
captureErrors: config.captureErrors ?? false,
|
|
26
|
+
debug: config.debug ?? false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The core Uptimizr client. Framework-agnostic: it owns the session, the event
|
|
31
|
+
* queue, batching/flush scheduling, and transport. Engine-specific capture is added
|
|
32
|
+
* via `use(collector)` (e.g. the Babylon adapter), keeping this package free of any
|
|
33
|
+
* 3D-engine dependency.
|
|
34
|
+
*
|
|
35
|
+
* Privacy: no cookies, no persistent client ID. The `sessionId` is in-memory only
|
|
36
|
+
* and the server assigns the cookieless `visitorId` during ingestion (ADR 0003).
|
|
37
|
+
*/
|
|
38
|
+
export class UptimizrClient {
|
|
39
|
+
config;
|
|
40
|
+
sessionId;
|
|
41
|
+
queue;
|
|
42
|
+
transport;
|
|
43
|
+
processor;
|
|
44
|
+
beforeSend;
|
|
45
|
+
collectors = [];
|
|
46
|
+
handles = [];
|
|
47
|
+
started = false;
|
|
48
|
+
startedAt = 0;
|
|
49
|
+
url;
|
|
50
|
+
currentScene = DEFAULT_SCENE_ID;
|
|
51
|
+
pageMeta;
|
|
52
|
+
flushTimer;
|
|
53
|
+
resizeTimer;
|
|
54
|
+
errorCount = 0;
|
|
55
|
+
lastErrorKey;
|
|
56
|
+
boundVisibility = () => this.onVisibilityChange();
|
|
57
|
+
boundPageHide = () => {
|
|
58
|
+
void this.stop("hidden");
|
|
59
|
+
};
|
|
60
|
+
boundFocus = () => this.onFocusChange(true);
|
|
61
|
+
boundBlur = () => this.onFocusChange(false);
|
|
62
|
+
boundResize = () => this.onResize();
|
|
63
|
+
boundError = (event) => this.onErrorEvent(event);
|
|
64
|
+
boundRejection = (event) => this.onUnhandledRejection(event);
|
|
65
|
+
constructor(config) {
|
|
66
|
+
this.config = resolveConfig(config);
|
|
67
|
+
this.sessionId = randomId();
|
|
68
|
+
this.queue = new EventQueue(this.config.maxQueueSize);
|
|
69
|
+
this.transport = config.transport ?? createBeaconTransport(this.config.endpoint);
|
|
70
|
+
this.processor = this.createProcessor(config);
|
|
71
|
+
this.beforeSend = config.beforeSend;
|
|
72
|
+
}
|
|
73
|
+
/** Register a capture plugin. Call before `start` (or after; it starts immediately). */
|
|
74
|
+
use(collector) {
|
|
75
|
+
this.collectors.push(collector);
|
|
76
|
+
if (this.started) {
|
|
77
|
+
this.startCollector(collector);
|
|
78
|
+
}
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
/** Begin the session: emit `session_start`, schedule flushing, and start collectors. */
|
|
82
|
+
start(meta = {}) {
|
|
83
|
+
if (this.started || this.config.disabled) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
this.started = true;
|
|
87
|
+
this.startedAt = this.now();
|
|
88
|
+
this.url = meta.url ?? this.defaultUrl();
|
|
89
|
+
this.pageMeta = meta.pageMeta;
|
|
90
|
+
// Apply the initial scene (if any) before session_start so it is stamped.
|
|
91
|
+
if (meta.sceneId != null) {
|
|
92
|
+
const parsed = sceneIdSchema.safeParse(meta.sceneId);
|
|
93
|
+
if (parsed.success) {
|
|
94
|
+
this.currentScene = parsed.data;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.log(`ignoring invalid initial sceneId: ${String(meta.sceneId)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
this.emit({
|
|
101
|
+
type: "session_start",
|
|
102
|
+
...(meta.device ? { device: meta.device } : {}),
|
|
103
|
+
...(meta.graphics ? { graphics: meta.graphics } : {}),
|
|
104
|
+
...(meta.scene ? { scene: meta.scene } : {}),
|
|
105
|
+
...(meta.connector ? { connector: meta.connector } : {}),
|
|
106
|
+
...(meta.user ? { user: meta.user } : {}),
|
|
107
|
+
});
|
|
108
|
+
if (this.config.flushIntervalMs > 0) {
|
|
109
|
+
this.flushTimer = setInterval(() => void this.flush(), this.config.flushIntervalMs);
|
|
110
|
+
}
|
|
111
|
+
this.bindLifecycle();
|
|
112
|
+
for (const collector of this.collectors) {
|
|
113
|
+
this.startCollector(collector);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Switch the active scene/area (ADR 0010). Stamps the new `sceneId` on every
|
|
118
|
+
* subsequent event and emits an ordered `scene_change` marker so the replay
|
|
119
|
+
* timeline records the transition. Invalid ids are ignored (logged in debug).
|
|
120
|
+
* No-ops if the scene is unchanged. May be called before `start`, in which case
|
|
121
|
+
* the scene is applied to `session_start`.
|
|
122
|
+
*/
|
|
123
|
+
setScene(sceneId) {
|
|
124
|
+
if (this.config.disabled) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const parsed = sceneIdSchema.safeParse(sceneId);
|
|
128
|
+
if (!parsed.success) {
|
|
129
|
+
this.log(`ignoring invalid sceneId: ${String(sceneId)}`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (parsed.data === this.currentScene) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.currentScene = parsed.data;
|
|
136
|
+
if (this.started) {
|
|
137
|
+
this.emit({ type: "scene_change" });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Build the envelope and queue an event. */
|
|
141
|
+
emit(input) {
|
|
142
|
+
if (!this.started || this.config.disabled) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const event = {
|
|
146
|
+
...input,
|
|
147
|
+
projectId: this.config.projectId,
|
|
148
|
+
sessionId: this.sessionId,
|
|
149
|
+
ts: this.now(),
|
|
150
|
+
sdkVersion: this.config.sdkVersion,
|
|
151
|
+
...(this.url ? { url: this.url } : {}),
|
|
152
|
+
...(this.currentScene !== DEFAULT_SCENE_ID ? { sceneId: this.currentScene } : {}),
|
|
153
|
+
...(this.pageMeta ? { pageMeta: this.pageMeta } : {}),
|
|
154
|
+
};
|
|
155
|
+
const finalEvent = this.beforeSend ? this.beforeSend(event) : event;
|
|
156
|
+
if (!finalEvent) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
this.queue.enqueue(finalEvent);
|
|
160
|
+
if (this.queue.size >= this.config.batchSize) {
|
|
161
|
+
void this.flush();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/** Emit a developer-defined `custom` event. */
|
|
165
|
+
track(name, props) {
|
|
166
|
+
this.emit({ type: "custom", name, ...(props ? { props } : {}) });
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Emit an `input_action` for a discrete, non-pointer input — a keyboard
|
|
170
|
+
* key/chord or a gamepad button bound to an app action (ADR 0023). This is the
|
|
171
|
+
* engine-neutral path: the host app reports the *semantic* action it mapped the
|
|
172
|
+
* input to. Pointer/ray inputs flow through the connector's `pointer_*` /
|
|
173
|
+
* `mesh_interaction` capture instead; continuous navigation stays in
|
|
174
|
+
* `camera_sample`.
|
|
175
|
+
*
|
|
176
|
+
* Privacy (ADR 0003): pass app-defined action labels only — never raw typed
|
|
177
|
+
* text. `source` defaults to `"keyboard"` since that is the most common caller.
|
|
178
|
+
*/
|
|
179
|
+
trackInput(action, opts = {}) {
|
|
180
|
+
if (!action) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this.emit({
|
|
184
|
+
type: "input_action",
|
|
185
|
+
action,
|
|
186
|
+
source: opts.source ?? "keyboard",
|
|
187
|
+
...(opts.code ? { code: opts.code } : {}),
|
|
188
|
+
...(typeof opts.button === "number" ? { button: opts.button } : {}),
|
|
189
|
+
...(typeof opts.pressed === "boolean" ? { pressed: opts.pressed } : {}),
|
|
190
|
+
...(opts.handedness ? { handedness: opts.handedness } : {}),
|
|
191
|
+
...(opts.sourceId ? { sourceId: opts.sourceId } : {}),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Report a capability / fidelity transition — a fallback or recovery (#49,
|
|
196
|
+
* design §E). Engines decide their backend at init and rarely expose a runtime
|
|
197
|
+
* "I downgraded" hook, so this is the engine-neutral, **app-reported** path: the
|
|
198
|
+
* host app describes the transition it performed (e.g. a WebGPU→WebGL2
|
|
199
|
+
* downgrade, a quality/LOD auto-downgrade, or a re-init after a lost device).
|
|
200
|
+
* This pairs with the raw `context_lost` / `context_restored` lifecycle events.
|
|
201
|
+
*
|
|
202
|
+
* Privacy (ADR 0003): pass low-cardinality, app-defined tokens only — never raw
|
|
203
|
+
* device strings or PII.
|
|
204
|
+
*/
|
|
205
|
+
reportCapabilityChange(change) {
|
|
206
|
+
if (!change.kind) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
this.emit({
|
|
210
|
+
type: "capability_change",
|
|
211
|
+
kind: change.kind,
|
|
212
|
+
...(change.from ? { from: change.from } : {}),
|
|
213
|
+
...(change.to ? { to: change.to } : {}),
|
|
214
|
+
...(change.reason ? { reason: change.reason } : {}),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/** Send all queued events. On failure, events are re-queued for the next attempt. */
|
|
218
|
+
async flush(opts) {
|
|
219
|
+
const events = this.queue.drain();
|
|
220
|
+
if (events.length === 0) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const batch = { schemaVersion: SCHEMA_VERSION, events };
|
|
224
|
+
// Steady-state batches may be offloaded to a worker; the terminal unload
|
|
225
|
+
// flush always runs on the main thread for delivery reliability (ADR 0031).
|
|
226
|
+
const ok = await (opts?.unload
|
|
227
|
+
? this.processor.processUnload(batch)
|
|
228
|
+
: this.processor.process(batch));
|
|
229
|
+
if (!ok) {
|
|
230
|
+
this.queue.prepend(events);
|
|
231
|
+
this.log("flush failed; re-queued", events.length);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/** End the session: emit `session_end`, flush, and tear down collectors/timers. */
|
|
235
|
+
async stop(reason = "manual") {
|
|
236
|
+
if (!this.started) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
this.emit({
|
|
240
|
+
type: "session_end",
|
|
241
|
+
durationMs: this.now() - this.startedAt,
|
|
242
|
+
reason,
|
|
243
|
+
});
|
|
244
|
+
this.started = false;
|
|
245
|
+
if (this.flushTimer) {
|
|
246
|
+
clearInterval(this.flushTimer);
|
|
247
|
+
this.flushTimer = undefined;
|
|
248
|
+
}
|
|
249
|
+
this.unbindLifecycle();
|
|
250
|
+
for (const handle of this.handles.splice(0)) {
|
|
251
|
+
handle.stop();
|
|
252
|
+
}
|
|
253
|
+
// Terminal flush on the main thread (beacon-reliable), then release the
|
|
254
|
+
// worker if one was running (ADR 0031).
|
|
255
|
+
await this.flush({ unload: true });
|
|
256
|
+
this.processor.dispose();
|
|
257
|
+
}
|
|
258
|
+
/** Current time in epoch ms. Isolated for test overrides. */
|
|
259
|
+
now() {
|
|
260
|
+
return Date.now();
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Choose the processor (ADR 0031). Defaults to the main-thread processor.
|
|
264
|
+
* `offload: "worker"` opts into a worker for steady-state serialization +
|
|
265
|
+
* dispatch, but only when no custom transport is set (a custom transport is a
|
|
266
|
+
* main-thread closure the worker cannot run) and a worker can actually be
|
|
267
|
+
* constructed; otherwise it transparently falls back to the main thread.
|
|
268
|
+
*/
|
|
269
|
+
createProcessor(config) {
|
|
270
|
+
if (this.config.offload === "worker") {
|
|
271
|
+
if (config.transport) {
|
|
272
|
+
this.log("custom transport set; worker offload disabled (transport runs on main thread)");
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const worker = createWorkerProcessor({
|
|
276
|
+
endpoint: this.config.endpoint,
|
|
277
|
+
unloadTransport: this.transport,
|
|
278
|
+
...(config.createWorker
|
|
279
|
+
? { workerFactory: config.createWorker }
|
|
280
|
+
: {}),
|
|
281
|
+
});
|
|
282
|
+
if (worker) {
|
|
283
|
+
return worker;
|
|
284
|
+
}
|
|
285
|
+
this.log("worker offload unavailable; falling back to main-thread processor");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return createMainProcessor(this.transport);
|
|
289
|
+
}
|
|
290
|
+
startCollector(collector) {
|
|
291
|
+
const ctx = {
|
|
292
|
+
config: this.config,
|
|
293
|
+
sessionId: this.sessionId,
|
|
294
|
+
emit: (event) => this.emit(event),
|
|
295
|
+
track: (name, props) => this.track(name, props),
|
|
296
|
+
trackInput: (action, opts) => this.trackInput(action, opts),
|
|
297
|
+
reportCapabilityChange: (change) => this.reportCapabilityChange(change),
|
|
298
|
+
setScene: (sceneId) => this.setScene(sceneId),
|
|
299
|
+
now: () => this.now(),
|
|
300
|
+
};
|
|
301
|
+
try {
|
|
302
|
+
const handle = collector.start(ctx);
|
|
303
|
+
if (handle) {
|
|
304
|
+
this.handles.push(handle);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
this.log(`collector "${collector.name}" failed to start`, err);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
onVisibilityChange() {
|
|
312
|
+
const doc = globalThis.document;
|
|
313
|
+
const hidden = doc?.visibilityState === "hidden";
|
|
314
|
+
if (this.config.captureLifecycle && doc) {
|
|
315
|
+
this.emit({ type: "visibility_change", state: hidden ? "hidden" : "visible" });
|
|
316
|
+
}
|
|
317
|
+
if (hidden) {
|
|
318
|
+
void this.flush({ unload: true });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
onFocusChange(focused) {
|
|
322
|
+
if (this.config.captureLifecycle) {
|
|
323
|
+
this.emit({ type: "focus_change", focused });
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
onResize() {
|
|
327
|
+
if (!this.config.captureLifecycle) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (this.resizeTimer) {
|
|
331
|
+
clearTimeout(this.resizeTimer);
|
|
332
|
+
}
|
|
333
|
+
this.resizeTimer = setTimeout(() => {
|
|
334
|
+
this.resizeTimer = undefined;
|
|
335
|
+
this.emitViewportResize();
|
|
336
|
+
}, this.config.resizeDebounceMs);
|
|
337
|
+
}
|
|
338
|
+
/** Emit a `viewport_resize` from the current window dimensions, if available. */
|
|
339
|
+
emitViewportResize() {
|
|
340
|
+
const g = globalThis;
|
|
341
|
+
if (typeof g.innerWidth !== "number" || typeof g.innerHeight !== "number") {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (g.innerWidth <= 0 || g.innerHeight <= 0) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
this.emit({
|
|
348
|
+
type: "viewport_resize",
|
|
349
|
+
width: g.innerWidth,
|
|
350
|
+
height: g.innerHeight,
|
|
351
|
+
...(typeof g.devicePixelRatio === "number" ? { dpr: g.devicePixelRatio } : {}),
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
/** Max `runtime_error` events emitted per session (ADR 0013 storm control). */
|
|
355
|
+
static MAX_ERRORS_PER_SESSION = 50;
|
|
356
|
+
onErrorEvent(event) {
|
|
357
|
+
this.emitError({
|
|
358
|
+
kind: "error",
|
|
359
|
+
message: event.message || "Unknown error",
|
|
360
|
+
...(event.filename ? { source: event.filename } : {}),
|
|
361
|
+
...(typeof event.lineno === "number" ? { lineno: event.lineno } : {}),
|
|
362
|
+
...(typeof event.colno === "number" ? { colno: event.colno } : {}),
|
|
363
|
+
...(event.error instanceof Error && event.error.stack ? { stack: event.error.stack } : {}),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
onUnhandledRejection(event) {
|
|
367
|
+
const reason = event.reason;
|
|
368
|
+
const message = reason instanceof Error
|
|
369
|
+
? reason.message
|
|
370
|
+
: typeof reason === "string"
|
|
371
|
+
? reason
|
|
372
|
+
: "Unhandled promise rejection";
|
|
373
|
+
this.emitError({
|
|
374
|
+
kind: "unhandledrejection",
|
|
375
|
+
message: message || "Unhandled promise rejection",
|
|
376
|
+
...(reason instanceof Error && reason.stack ? { stack: reason.stack } : {}),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Emit a `runtime_error`, applying ADR 0013 storm control: drop a consecutive
|
|
381
|
+
* duplicate (same message+stack) and cap the total per session. Free-text
|
|
382
|
+
* fields are length-bounded to match the schema; deeper redaction is the
|
|
383
|
+
* deployer's job via `beforeSend`.
|
|
384
|
+
*/
|
|
385
|
+
emitError(input) {
|
|
386
|
+
if (this.errorCount >= UptimizrClient.MAX_ERRORS_PER_SESSION)
|
|
387
|
+
return;
|
|
388
|
+
const key = `${input.message}\u0000${input.stack ?? ""}`;
|
|
389
|
+
if (key === this.lastErrorKey)
|
|
390
|
+
return;
|
|
391
|
+
this.lastErrorKey = key;
|
|
392
|
+
this.errorCount += 1;
|
|
393
|
+
this.emit({
|
|
394
|
+
type: "runtime_error",
|
|
395
|
+
kind: input.kind,
|
|
396
|
+
message: input.message.slice(0, 1024),
|
|
397
|
+
...(input.source ? { source: input.source.slice(0, 1024) } : {}),
|
|
398
|
+
...(typeof input.lineno === "number" ? { lineno: input.lineno } : {}),
|
|
399
|
+
...(typeof input.colno === "number" ? { colno: input.colno } : {}),
|
|
400
|
+
...(input.stack ? { stack: input.stack.slice(0, 4096) } : {}),
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
bindLifecycle() {
|
|
404
|
+
const doc = globalThis.document;
|
|
405
|
+
const win = globalThis.addEventListener
|
|
406
|
+
? globalThis
|
|
407
|
+
: undefined;
|
|
408
|
+
doc?.addEventListener("visibilitychange", this.boundVisibility);
|
|
409
|
+
win?.addEventListener("pagehide", this.boundPageHide);
|
|
410
|
+
if (this.config.captureLifecycle && win) {
|
|
411
|
+
win.addEventListener("focus", this.boundFocus);
|
|
412
|
+
win.addEventListener("blur", this.boundBlur);
|
|
413
|
+
win.addEventListener("resize", this.boundResize);
|
|
414
|
+
// Emit an initial viewport sample so every session has a known starting
|
|
415
|
+
// viewport for heatmap normalization.
|
|
416
|
+
this.emitViewportResize();
|
|
417
|
+
}
|
|
418
|
+
if (this.config.captureErrors && win) {
|
|
419
|
+
win.addEventListener("error", this.boundError);
|
|
420
|
+
win.addEventListener("unhandledrejection", this.boundRejection);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
unbindLifecycle() {
|
|
424
|
+
const doc = globalThis.document;
|
|
425
|
+
const win = globalThis
|
|
426
|
+
.removeEventListener
|
|
427
|
+
? globalThis
|
|
428
|
+
: undefined;
|
|
429
|
+
doc?.removeEventListener("visibilitychange", this.boundVisibility);
|
|
430
|
+
win?.removeEventListener("pagehide", this.boundPageHide);
|
|
431
|
+
win?.removeEventListener("focus", this.boundFocus);
|
|
432
|
+
win?.removeEventListener("blur", this.boundBlur);
|
|
433
|
+
win?.removeEventListener("resize", this.boundResize);
|
|
434
|
+
win?.removeEventListener("error", this.boundError);
|
|
435
|
+
win?.removeEventListener("unhandledrejection", this.boundRejection);
|
|
436
|
+
if (this.resizeTimer) {
|
|
437
|
+
clearTimeout(this.resizeTimer);
|
|
438
|
+
this.resizeTimer = undefined;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
defaultUrl() {
|
|
442
|
+
const loc = globalThis.location;
|
|
443
|
+
return loc?.href;
|
|
444
|
+
}
|
|
445
|
+
log(...args) {
|
|
446
|
+
if (this.config.debug) {
|
|
447
|
+
console.debug("[uptimizr]", ...args);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Aabb, CoordinateHandedness, Quat, Vec3 } from "@uptimizr/schema";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical world coordinate frame for everything on the wire (ADR 0018):
|
|
4
|
+
* **left-handed, y-up, unit scale 1** (Babylon-native). Connectors normalize their
|
|
5
|
+
* engine's world-space data to this frame at the emission boundary and record their
|
|
6
|
+
* native frame as provenance on `session_start`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CANONICAL_FRAME: {
|
|
9
|
+
readonly handedness: "left";
|
|
10
|
+
readonly upAxis: "y";
|
|
11
|
+
readonly unitScale: 1;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Convert a **world-space position** from a source engine's frame to the canonical
|
|
15
|
+
* frame (left-handed, y-up).
|
|
16
|
+
*
|
|
17
|
+
* Assumes a **y-up** source (true for three.js, glTF, PlayCanvas, Babylon). For a
|
|
18
|
+
* right-handed source the handedness flip is the reflection `diag(1, 1, -1)` —
|
|
19
|
+
* i.e. negate Z. A left-handed source is already canonical and is returned
|
|
20
|
+
* unchanged (a fresh copy). Non-y-up sources are out of scope; the connector must
|
|
21
|
+
* rebase to y-up before calling.
|
|
22
|
+
*/
|
|
23
|
+
export declare function toCanonicalPosition(p: Vec3, sourceHandedness: CoordinateHandedness): Vec3;
|
|
24
|
+
/**
|
|
25
|
+
* Convert a **world-space direction vector** (e.g. a camera's forward ray) from a
|
|
26
|
+
* source engine's frame to the canonical frame. Same reflection as
|
|
27
|
+
* {@link toCanonicalPosition} — directions ignore translation, so a right-handed
|
|
28
|
+
* source negates Z.
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ Orientation is convention-dependent, and this is the common trap. A camera's
|
|
31
|
+
* *look direction* differs per engine: three.js cameras look along local **−Z**,
|
|
32
|
+
* the canonical (Babylon-style) camera looks along local **+Z**. This helper is
|
|
33
|
+
* correct **only when you pass a true world-space direction** (the actual look
|
|
34
|
+
* vector in world coordinates). If you instead reconstruct orientation from a
|
|
35
|
+
* **local quaternion / Euler**, reflecting components is **not** enough — you must
|
|
36
|
+
* also apply a rotation (a forward-axis flip / ~180° about the up axis) to account
|
|
37
|
+
* for the −Z vs +Z forward convention. Capture orientation as a world-space
|
|
38
|
+
* forward (and up) direction *before* converting.
|
|
39
|
+
*/
|
|
40
|
+
export declare function toCanonicalDirection(d: Vec3, sourceHandedness: CoordinateHandedness): Vec3;
|
|
41
|
+
/**
|
|
42
|
+
* Convert a world-space axis-aligned bounding box `[minX, minY, minZ, maxX, maxY,
|
|
43
|
+
* maxZ]` to the canonical frame. Negating the Z axis swaps the Z min/max, so the
|
|
44
|
+
* result stays a well-formed AABB (min ≤ max per axis).
|
|
45
|
+
*/
|
|
46
|
+
export declare function toCanonicalAabb(aabb: Aabb, sourceHandedness: CoordinateHandedness): Aabb;
|
|
47
|
+
/**
|
|
48
|
+
* Convert a **world-space position** from the canonical frame back into a target
|
|
49
|
+
* engine's native frame — the inverse of {@link toCanonicalPosition}. Used by
|
|
50
|
+
* replay drivers, which read canonical events off the wire and write them into a
|
|
51
|
+
* host scene (e.g. re-driving a three.js camera).
|
|
52
|
+
*
|
|
53
|
+
* The handedness flip is the reflection `diag(1, 1, -1)`, which is its own
|
|
54
|
+
* inverse, so this delegates to the same basis change — but the named inverse
|
|
55
|
+
* keeps replay/host code self-documenting (canonical → engine).
|
|
56
|
+
*/
|
|
57
|
+
export declare function fromCanonicalPosition(p: Vec3, targetHandedness: CoordinateHandedness): Vec3;
|
|
58
|
+
/**
|
|
59
|
+
* Convert a **world-space direction vector** from the canonical frame back into a
|
|
60
|
+
* target engine's native frame — the inverse of {@link toCanonicalDirection}.
|
|
61
|
+
*
|
|
62
|
+
* The same orientation caveat applies in reverse: this yields a correct
|
|
63
|
+
* world-space direction, but a host that needs a *camera orientation* should
|
|
64
|
+
* point the camera at a converted world-space target (e.g. `camera.lookAt`)
|
|
65
|
+
* rather than feeding this into a local-rotation reconstruction.
|
|
66
|
+
*/
|
|
67
|
+
export declare function fromCanonicalDirection(d: Vec3, targetHandedness: CoordinateHandedness): Vec3;
|
|
68
|
+
/**
|
|
69
|
+
* Convert a world-space AABB from the canonical frame back into a target engine's
|
|
70
|
+
* native frame — the inverse of {@link toCanonicalAabb} (Z min/max swap is its
|
|
71
|
+
* own inverse, so the box stays well-formed).
|
|
72
|
+
*/
|
|
73
|
+
export declare function fromCanonicalAabb(aabb: Aabb, targetHandedness: CoordinateHandedness): Aabb;
|
|
74
|
+
/**
|
|
75
|
+
* Convert a **world-space orientation quaternion** `[x, y, z, w]` from a source
|
|
76
|
+
* engine's frame to the canonical frame (left-handed, y-up). Used for
|
|
77
|
+
* `node_transform` (ADR 0027): a scene actor's world rotation.
|
|
78
|
+
*
|
|
79
|
+
* The handedness flip is the same reflection as {@link toCanonicalPosition}
|
|
80
|
+
* (`diag(1, 1, -1)`, i.e. negate Z). Conjugating a rotation by that reflection
|
|
81
|
+
* maps the quaternion `(x, y, z, w) → (-x, -y, z, w)`: the reflected rotation
|
|
82
|
+
* axis is `(ax, ay, -az)` while the handedness flip negates the angle, and the
|
|
83
|
+
* two sign changes combine to leave only `x` and `y` negated. A left-handed
|
|
84
|
+
* source is already canonical and returned as a copy.
|
|
85
|
+
*
|
|
86
|
+
* Unlike a camera's *look direction* (whose forward-axis convention differs per
|
|
87
|
+
* engine — see {@link toCanonicalDirection}), an object's world rotation has no
|
|
88
|
+
* such convention, so this conversion is exact for scene-actor orientation.
|
|
89
|
+
*/
|
|
90
|
+
export declare function toCanonicalQuat(q: Quat, sourceHandedness: CoordinateHandedness): Quat;
|
|
91
|
+
/**
|
|
92
|
+
* Convert a **world-space orientation quaternion** from the canonical frame back
|
|
93
|
+
* into a target engine's native frame — the inverse of {@link toCanonicalQuat}.
|
|
94
|
+
* The reflection is its own inverse, so this delegates to the same basis change;
|
|
95
|
+
* the named inverse keeps replay/host code self-documenting (canonical → engine).
|
|
96
|
+
*/
|
|
97
|
+
export declare function fromCanonicalQuat(q: Quat, targetHandedness: CoordinateHandedness): Quat;
|
|
98
|
+
//# sourceMappingURL=coordinates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinates.d.ts","sourceRoot":"","sources":["../src/coordinates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAOX;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAGzF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAG1F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAMxF;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAE3F;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAE1F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAGrF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,oBAAoB,GAAG,IAAI,CAEvF"}
|