@proappstore/sdk 1.16.43 → 1.16.45
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 +58 -0
- package/dist/actions.d.ts +2 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +2 -2
- package/dist/actions.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +33 -4
- package/dist/auth.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/logs.d.ts +96 -0
- package/dist/logs.d.ts.map +1 -0
- package/dist/logs.js +298 -0
- package/dist/logs.js.map +1 -0
- package/dist/telemetry-transport.d.ts +36 -0
- package/dist/telemetry-transport.d.ts.map +1 -0
- package/dist/telemetry-transport.js +56 -0
- package/dist/telemetry-transport.js.map +1 -0
- package/dist/types.d.ts +11 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +10 -40
- package/dist/usage.js.map +1 -1
- package/package.json +1 -1
- package/dist/monitoring.d.ts +0 -58
- package/dist/monitoring.d.ts.map +0 -1
- package/dist/monitoring.js +0 -146
- package/dist/monitoring.js.map +0 -1
package/dist/logs.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App logging + automatic runtime error capture (platform#105, ADR-008).
|
|
3
|
+
*
|
|
4
|
+
* Auto-started by `initPro()` unless `monitoring.auto === false`. Captures
|
|
5
|
+
* `window.onerror` and `unhandledrejection`, batches entries, and flushes them to
|
|
6
|
+
* `POST /v1/apps/:appId/logs`, where the app owner reads them in the console.
|
|
7
|
+
*
|
|
8
|
+
* Design notes:
|
|
9
|
+
*
|
|
10
|
+
* - **Works signed out.** Anonymous reports are the point: a white screen on load
|
|
11
|
+
* or a broken sign-in has no session, and those are the failures worth having.
|
|
12
|
+
* A rotating per-install `clientId` gives them a cardinality without naming a
|
|
13
|
+
* person.
|
|
14
|
+
* - **Browser-only.** Every method no-ops without `window`, so the import stays
|
|
15
|
+
* SSR-safe.
|
|
16
|
+
* - **Silent.** No throw path, ever. A logger that breaks the app it observes is
|
|
17
|
+
* worse than no logger.
|
|
18
|
+
* - **Backs off instead of retrying.** The server answers 202 when an app is over
|
|
19
|
+
* its budget; retrying would turn an error loop into a flood. See `cooldown`.
|
|
20
|
+
* - **Not a replacement for usage telemetry.** `app.usage` is unchanged; the two
|
|
21
|
+
* share only the transport.
|
|
22
|
+
*/
|
|
23
|
+
import { postTelemetry } from './telemetry-transport.js';
|
|
24
|
+
const FLUSH_INTERVAL_MS = 10_000;
|
|
25
|
+
/** Matches the server's per-request cap; a full queue flushes immediately. */
|
|
26
|
+
const MAX_BATCH = 100;
|
|
27
|
+
/** Hard ceiling while offline or backing off. Oldest entries are dropped. */
|
|
28
|
+
const MAX_QUEUE = 200;
|
|
29
|
+
/** How long to stay quiet after the server says we are over budget. */
|
|
30
|
+
const COOLDOWN_MS = 60_000;
|
|
31
|
+
const MESSAGE_MAX = 4096;
|
|
32
|
+
const CLIENT_ID_KEY = 'pas:client-id';
|
|
33
|
+
const LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
34
|
+
/**
|
|
35
|
+
* Redact secret-shaped substrings before anything leaves the browser.
|
|
36
|
+
*
|
|
37
|
+
* Vendored deliberately rather than shared with the backend (the SDK ships to npm
|
|
38
|
+
* and cannot import a private package). The server scrubs again at ingest — this
|
|
39
|
+
* copy exists so a secret never crosses the network in the first place.
|
|
40
|
+
*/
|
|
41
|
+
const REDACTIONS = [
|
|
42
|
+
[/\bBearer\s+[\w\-._~+/]+=*/gi, 'Bearer [redacted]'],
|
|
43
|
+
[
|
|
44
|
+
/\b(password|passwd|pwd|secret|token|api[_-]?key|authorization|cookie|client[_-]?secret)\b("?\s*[:=]\s*)("?)[^\s,;"}&]+\3/gi,
|
|
45
|
+
'$1$2[redacted]',
|
|
46
|
+
],
|
|
47
|
+
[/\beyJ[\w-]+\.[\w-]+\.[\w-]+/g, '[jwt]'],
|
|
48
|
+
[/\b[\w.+-]+@[\w-]+\.[\w.-]{2,}\b/g, '[email]'],
|
|
49
|
+
[/\b[A-Fa-f0-9]{32,}\b/g, '[hex]'],
|
|
50
|
+
];
|
|
51
|
+
export function redactClient(input) {
|
|
52
|
+
let out = input;
|
|
53
|
+
for (const [pattern, replacement] of REDACTIONS)
|
|
54
|
+
out = out.replace(pattern, replacement);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
function hasBrowser() {
|
|
58
|
+
return typeof window !== 'undefined';
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Stable-per-install id, created on first use.
|
|
62
|
+
*
|
|
63
|
+
* Not a person identifier: it lives in this browser's storage, clears with site
|
|
64
|
+
* data, and is never correlated across apps. It exists so an owner can tell "one
|
|
65
|
+
* user hit this 40 times" from "40 users hit it once" for reports that have no
|
|
66
|
+
* session at all.
|
|
67
|
+
*/
|
|
68
|
+
export function readOrCreateClientId() {
|
|
69
|
+
if (!hasBrowser())
|
|
70
|
+
return null;
|
|
71
|
+
try {
|
|
72
|
+
const existing = window.localStorage.getItem(CLIENT_ID_KEY);
|
|
73
|
+
if (existing && /^[A-Za-z0-9_-]{8,64}$/.test(existing))
|
|
74
|
+
return existing;
|
|
75
|
+
const bytes = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
|
|
76
|
+
? crypto.randomUUID().replace(/-/g, '')
|
|
77
|
+
: Math.random().toString(36).slice(2).padEnd(24, '0');
|
|
78
|
+
const id = bytes.slice(0, 24);
|
|
79
|
+
window.localStorage.setItem(CLIENT_ID_KEY, id);
|
|
80
|
+
return id;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Incognito, blocked storage, quota — anonymous reports still work, they
|
|
84
|
+
// just lose their per-install grouping.
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** Serialize an unknown thrown value into a message + stack. */
|
|
89
|
+
export function describeError(value) {
|
|
90
|
+
if (value instanceof Error) {
|
|
91
|
+
return { message: `${value.name}: ${value.message}`, stack: value.stack ?? undefined };
|
|
92
|
+
}
|
|
93
|
+
if (typeof value === 'string')
|
|
94
|
+
return { message: value };
|
|
95
|
+
try {
|
|
96
|
+
return { message: JSON.stringify(value) ?? String(value) };
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return { message: String(value) };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export class Logs {
|
|
103
|
+
appId;
|
|
104
|
+
apiBase;
|
|
105
|
+
auth;
|
|
106
|
+
options;
|
|
107
|
+
queue = [];
|
|
108
|
+
running = false;
|
|
109
|
+
timer = null;
|
|
110
|
+
onError = null;
|
|
111
|
+
onRejection = null;
|
|
112
|
+
onPageHide = null;
|
|
113
|
+
clientId = null;
|
|
114
|
+
/** Epoch ms until which we send nothing (server asked us to stop). */
|
|
115
|
+
quietUntil = 0;
|
|
116
|
+
/** Set when the server says this app cannot accept logs at all (404). */
|
|
117
|
+
disabled = false;
|
|
118
|
+
/** Guards against an error raised inside our own handler re-entering. */
|
|
119
|
+
capturing = false;
|
|
120
|
+
minLevel;
|
|
121
|
+
constructor(appId, apiBase, auth, options = {}) {
|
|
122
|
+
this.appId = appId;
|
|
123
|
+
this.apiBase = apiBase;
|
|
124
|
+
this.auth = auth;
|
|
125
|
+
this.options = options;
|
|
126
|
+
this.minLevel = options.level ?? 'info';
|
|
127
|
+
}
|
|
128
|
+
/** Begin auto-capture and periodic flushing. Idempotent. */
|
|
129
|
+
start() {
|
|
130
|
+
if (this.running || !hasBrowser())
|
|
131
|
+
return;
|
|
132
|
+
this.running = true;
|
|
133
|
+
this.clientId = readOrCreateClientId();
|
|
134
|
+
this.onError = (event) => {
|
|
135
|
+
const described = event.error
|
|
136
|
+
? describeError(event.error)
|
|
137
|
+
: { message: event.message || 'unknown error' };
|
|
138
|
+
this.capture('error', 'window.error', described.message, {
|
|
139
|
+
stack: described.stack,
|
|
140
|
+
source: event.filename || undefined,
|
|
141
|
+
line: event.lineno || undefined,
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
window.addEventListener('error', this.onError);
|
|
145
|
+
this.onRejection = (event) => {
|
|
146
|
+
const described = describeError(event.reason);
|
|
147
|
+
this.capture('error', 'unhandledrejection', described.message, {
|
|
148
|
+
stack: described.stack,
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
window.addEventListener('unhandledrejection', this.onRejection);
|
|
152
|
+
this.onPageHide = () => this.flush();
|
|
153
|
+
window.addEventListener('pagehide', this.onPageHide);
|
|
154
|
+
this.timer = setInterval(() => {
|
|
155
|
+
void this.send(false);
|
|
156
|
+
}, FLUSH_INTERVAL_MS);
|
|
157
|
+
}
|
|
158
|
+
/** Stop capture and timers. Does not flush — call `flush()` first if needed. */
|
|
159
|
+
stop() {
|
|
160
|
+
if (!this.running)
|
|
161
|
+
return;
|
|
162
|
+
this.running = false;
|
|
163
|
+
if (this.timer) {
|
|
164
|
+
clearInterval(this.timer);
|
|
165
|
+
this.timer = null;
|
|
166
|
+
}
|
|
167
|
+
if (hasBrowser()) {
|
|
168
|
+
if (this.onError)
|
|
169
|
+
window.removeEventListener('error', this.onError);
|
|
170
|
+
if (this.onRejection)
|
|
171
|
+
window.removeEventListener('unhandledrejection', this.onRejection);
|
|
172
|
+
if (this.onPageHide)
|
|
173
|
+
window.removeEventListener('pagehide', this.onPageHide);
|
|
174
|
+
}
|
|
175
|
+
this.onError = null;
|
|
176
|
+
this.onRejection = null;
|
|
177
|
+
this.onPageHide = null;
|
|
178
|
+
}
|
|
179
|
+
debug(message, data) {
|
|
180
|
+
this.capture('debug', 'app', message, data);
|
|
181
|
+
}
|
|
182
|
+
info(message, data) {
|
|
183
|
+
this.capture('info', 'app', message, data);
|
|
184
|
+
}
|
|
185
|
+
warn(message, data) {
|
|
186
|
+
this.capture('warn', 'app', message, data);
|
|
187
|
+
}
|
|
188
|
+
error(message, data) {
|
|
189
|
+
this.capture('error', 'app', message, data);
|
|
190
|
+
}
|
|
191
|
+
/** Number of entries waiting to be sent. Exposed for tests and diagnostics. */
|
|
192
|
+
get pending() {
|
|
193
|
+
return this.queue.length;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Queue one entry.
|
|
197
|
+
*
|
|
198
|
+
* Public so app code can record its own categories (`app.logs.capture('warn',
|
|
199
|
+
* 'checkout', ...)`), and so SDK primitives can report their own failures
|
|
200
|
+
* (platform#106's client half) without another queue.
|
|
201
|
+
*/
|
|
202
|
+
capture(level, category, message, data) {
|
|
203
|
+
if (this.disabled || this.capturing)
|
|
204
|
+
return;
|
|
205
|
+
if (LEVEL_ORDER[level] < LEVEL_ORDER[this.minLevel])
|
|
206
|
+
return;
|
|
207
|
+
this.capturing = true;
|
|
208
|
+
try {
|
|
209
|
+
const entry = {
|
|
210
|
+
ts: Date.now(),
|
|
211
|
+
level,
|
|
212
|
+
category,
|
|
213
|
+
message: redactClient(String(message)).slice(0, MESSAGE_MAX),
|
|
214
|
+
data: data === undefined ? undefined : this.safeData(data),
|
|
215
|
+
build: this.options.build,
|
|
216
|
+
traceId: this.newTraceId(),
|
|
217
|
+
};
|
|
218
|
+
this.queue.push(entry);
|
|
219
|
+
// Drop the OLDEST on overflow: during a loop the newest entries are all
|
|
220
|
+
// the same fault, while the first entries include what preceded it.
|
|
221
|
+
if (this.queue.length > MAX_QUEUE)
|
|
222
|
+
this.queue.splice(0, this.queue.length - MAX_QUEUE);
|
|
223
|
+
if (this.queue.length >= MAX_BATCH)
|
|
224
|
+
void this.send(false);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// Never let capture throw into app code.
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
this.capturing = false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/** Fire-and-forget flush, safe on the unload path. */
|
|
234
|
+
flush() {
|
|
235
|
+
void this.send(true);
|
|
236
|
+
}
|
|
237
|
+
/** Await a flush. For tests and deliberate checkpoints. */
|
|
238
|
+
async flushAsync() {
|
|
239
|
+
await this.send(false);
|
|
240
|
+
}
|
|
241
|
+
safeData(data) {
|
|
242
|
+
try {
|
|
243
|
+
return JSON.parse(redactClient(JSON.stringify(data) ?? 'null'));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// Cyclic, BigInt, or a getter that throws — keep the entry, drop the payload.
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/** W3C traceparent trace-id, so a client entry can be lined up with the
|
|
251
|
+
* backend and data-worker records for the same logical request. */
|
|
252
|
+
newTraceId() {
|
|
253
|
+
try {
|
|
254
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
255
|
+
return crypto.randomUUID().replace(/-/g, '');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
/* fall through */
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
async send(keepalive) {
|
|
264
|
+
if (this.disabled || this.queue.length === 0)
|
|
265
|
+
return;
|
|
266
|
+
if (Date.now() < this.quietUntil)
|
|
267
|
+
return;
|
|
268
|
+
const batch = this.queue.slice(0, MAX_BATCH);
|
|
269
|
+
// Remove before sending: a retry loop is worse than losing a log line, and
|
|
270
|
+
// the entries most likely to be dropped are duplicates of a fault we already
|
|
271
|
+
// reported.
|
|
272
|
+
this.queue = this.queue.slice(batch.length);
|
|
273
|
+
const body = JSON.stringify({
|
|
274
|
+
entries: batch,
|
|
275
|
+
...(this.clientId ? { clientId: this.clientId } : {}),
|
|
276
|
+
});
|
|
277
|
+
const res = await postTelemetry(this.auth, this.apiBase, `/v1/apps/${this.appId}/logs`, body, {
|
|
278
|
+
keepalive,
|
|
279
|
+
// A beacon cannot carry the bearer token, so only use it where the
|
|
280
|
+
// same-origin cookie speaks for us. In legacy-bearer mode a keepalive
|
|
281
|
+
// fetch still attaches the token and still survives unload in practice.
|
|
282
|
+
beacon: this.auth.usesPlatformCookie === true,
|
|
283
|
+
});
|
|
284
|
+
if (!res)
|
|
285
|
+
return;
|
|
286
|
+
if (res.status === 404) {
|
|
287
|
+
// Unknown app id — a misconfigured `appId` will never succeed, so stop
|
|
288
|
+
// rather than retry every ten seconds for the life of the page.
|
|
289
|
+
this.disabled = true;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (res.status === 202 || res.status === 429) {
|
|
293
|
+
// Over budget. Go quiet; the server is still counting the spike.
|
|
294
|
+
this.quietUntil = Date.now() + COOLDOWN_MS;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=logs.js.map
|
package/dist/logs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared POST transport for SDK telemetry (usage pings, app logs).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from usage.ts rather than reimplemented for the logger: the awkward
|
|
5
|
+
* parts — same-origin mediated URL vs absolute API base, bearer-vs-cookie auth,
|
|
6
|
+
* and `sendBeacon` on unload — were already solved there, and a second copy
|
|
7
|
+
* would drift.
|
|
8
|
+
*
|
|
9
|
+
* Never throws and never rejects. Telemetry must not break an app.
|
|
10
|
+
*/
|
|
11
|
+
export interface TelemetryAuth {
|
|
12
|
+
token: string | null;
|
|
13
|
+
usesPlatformCookie?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** In platform-cookie mode all calls go same-origin through the host's mediation
|
|
16
|
+
* so the HttpOnly cookie rides along (and the host can assert the app id). */
|
|
17
|
+
export declare function telemetryUrl(auth: TelemetryAuth, apiBase: string, path: string): string;
|
|
18
|
+
export interface PostOptions {
|
|
19
|
+
/** Unload path: prefer a transport that survives page close. */
|
|
20
|
+
keepalive?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether `sendBeacon` is acceptable for this payload.
|
|
23
|
+
*
|
|
24
|
+
* Beacons cannot set `Authorization`. In platform-cookie mode the same-origin
|
|
25
|
+
* beacon still carries the session cookie, so nothing is lost; in
|
|
26
|
+
* legacy-bearer mode the request would arrive unauthenticated, which each
|
|
27
|
+
* caller has to decide about for itself.
|
|
28
|
+
*/
|
|
29
|
+
beacon?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* POST a JSON body. Returns the Response, or null when the request could not be
|
|
33
|
+
* made or was sent via `sendBeacon` (which yields no response).
|
|
34
|
+
*/
|
|
35
|
+
export declare function postTelemetry(auth: TelemetryAuth, apiBase: string, path: string, body: string, opts?: PostOptions): Promise<Response | null>;
|
|
36
|
+
//# sourceMappingURL=telemetry-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-transport.d.ts","sourceRoot":"","sources":["../src/telemetry-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAkC1B"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared POST transport for SDK telemetry (usage pings, app logs).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from usage.ts rather than reimplemented for the logger: the awkward
|
|
5
|
+
* parts — same-origin mediated URL vs absolute API base, bearer-vs-cookie auth,
|
|
6
|
+
* and `sendBeacon` on unload — were already solved there, and a second copy
|
|
7
|
+
* would drift.
|
|
8
|
+
*
|
|
9
|
+
* Never throws and never rejects. Telemetry must not break an app.
|
|
10
|
+
*/
|
|
11
|
+
/** In platform-cookie mode all calls go same-origin through the host's mediation
|
|
12
|
+
* so the HttpOnly cookie rides along (and the host can assert the app id). */
|
|
13
|
+
export function telemetryUrl(auth, apiBase, path) {
|
|
14
|
+
return auth.usesPlatformCookie ? `/.pas/api${path}` : `${apiBase}${path}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* POST a JSON body. Returns the Response, or null when the request could not be
|
|
18
|
+
* made or was sent via `sendBeacon` (which yields no response).
|
|
19
|
+
*/
|
|
20
|
+
export async function postTelemetry(auth, apiBase, path, body, opts = {}) {
|
|
21
|
+
const url = telemetryUrl(auth, apiBase, path);
|
|
22
|
+
const keepalive = opts.keepalive === true;
|
|
23
|
+
if (keepalive &&
|
|
24
|
+
opts.beacon !== false &&
|
|
25
|
+
typeof navigator !== 'undefined' &&
|
|
26
|
+
typeof navigator.sendBeacon === 'function') {
|
|
27
|
+
try {
|
|
28
|
+
const blob = new Blob([body], { type: 'application/json' });
|
|
29
|
+
if (navigator.sendBeacon(url, blob))
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Fall through to fetch.
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (typeof fetch === 'undefined')
|
|
37
|
+
return null;
|
|
38
|
+
try {
|
|
39
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
40
|
+
const init = { method: 'POST', headers, body, keepalive };
|
|
41
|
+
if (auth.usesPlatformCookie) {
|
|
42
|
+
init.credentials = 'same-origin';
|
|
43
|
+
}
|
|
44
|
+
else if (auth.token) {
|
|
45
|
+
headers.Authorization = `Bearer ${auth.token}`;
|
|
46
|
+
}
|
|
47
|
+
// No token and no cookie is not an error here: log ingestion accepts
|
|
48
|
+
// anonymous reports on purpose, since a failure before sign-in is exactly
|
|
49
|
+
// the one worth having.
|
|
50
|
+
return await fetch(url, init);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=telemetry-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-transport.js","sourceRoot":"","sources":["../src/telemetry-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;+EAC+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAmB,EAAE,OAAe,EAAE,IAAY;IAC7E,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,CAAC;AAC5E,CAAC;AAgBD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAmB,EACnB,OAAe,EACf,IAAY,EACZ,IAAY,EACZ,OAAoB,EAAE;IAEtB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;IAE1C,IACE,SAAS;QACT,IAAI,CAAC,MAAM,KAAK,KAAK;QACrB,OAAO,SAAS,KAAK,WAAW;QAChC,OAAO,SAAS,CAAC,UAAU,KAAK,UAAU,EAC1C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC5D,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;QAC/E,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACvE,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,aAAa,GAAG,UAAU,IAAI,CAAC,KAAK,EAAE,CAAC;QACjD,CAAC;QACD,qEAAqE;QACrE,0EAA0E;QAC1E,wBAAwB;QACxB,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -21,12 +21,20 @@ export interface ProInitOptions {
|
|
|
21
21
|
/** Default true. Set false to disable the auto-heartbeat in this app. */
|
|
22
22
|
auto?: boolean;
|
|
23
23
|
};
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Runtime error capture (`app.logs`). On by default: `window.onerror` and
|
|
26
|
+
* `unhandledrejection` are recorded so a user-visible failure leaves a platform
|
|
27
|
+
* record, readable by the app owner in the console.
|
|
28
|
+
*
|
|
29
|
+
* Independent of `usage` above — that measures engagement, this records faults.
|
|
30
|
+
*/
|
|
25
31
|
monitoring?: {
|
|
26
|
-
/** Default true. Set false to disable auto
|
|
32
|
+
/** Default true. Set false to disable auto-capture and the flush timer. */
|
|
27
33
|
auto?: boolean;
|
|
28
|
-
/** Build metadata (commit, version,
|
|
34
|
+
/** Build metadata attached to every entry (commit sha, version, built-at). */
|
|
29
35
|
build?: Record<string, unknown>;
|
|
36
|
+
/** Minimum level sent. Default 'info', so `app.logs.debug()` is dropped. */
|
|
37
|
+
level?: 'debug' | 'info' | 'warn' | 'error';
|
|
30
38
|
};
|
|
31
39
|
}
|
|
32
40
|
export type SubscriptionStatus = 'active' | 'past_due' | 'canceled' | 'incomplete';
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC/C,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8GAA8G;IAC9G,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,KAAK,CAAC,EAAE;QACN,yEAAyE;QACzE,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC/C,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8GAA8G;IAC9G,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,KAAK,CAAC,EAAE;QACN,yEAAyE;QACzE,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF;;;;;;OAMG;IACH,UAAU,CAAC,EAAE;QACX,2EAA2E;QAC3E,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,8EAA8E;QAC9E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,4EAA4E;QAC5E,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;KAC7C,CAAC;CACH;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,CAAC;AAEnF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
|
package/dist/usage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AASD,qBAAa,KAAK;IAWd,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,YAAY,CAAuB;IAC3C,gFAAgF;IAChF,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,UAAU,CAA6B;gBAG5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ;IAGjC,wEAAwE;IACxE,KAAK,IAAI,IAAI;IA6Bb,iFAAiF;IACjF,IAAI,IAAI,IAAI;IAkBZ;;;OAGG;IACH,aAAa,CAAC,CAAC,GAAE,MAAU,GAAG,IAAI;IAKlC;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAWb,+DAA+D;IAC/D,OAAO,CAAC,WAAW;IAOnB,qFAAqF;IACrF,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;YAMP,IAAI;YAoBJ,IAAI;IAkBlB,OAAO,CAAC,eAAe;CAGxB"}
|
package/dist/usage.js
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* residual elapsed seconds via `navigator.sendBeacon` (survives unload)
|
|
19
19
|
* falling back to `fetch(..., { keepalive: true })`.
|
|
20
20
|
*/
|
|
21
|
+
import { postTelemetry } from './telemetry-transport.js';
|
|
21
22
|
const HEARTBEAT_MS = 60_000;
|
|
22
23
|
const MAX_DELTA_SECONDS = 90;
|
|
23
24
|
function hasBrowser() {
|
|
@@ -169,46 +170,15 @@ export class Usage {
|
|
|
169
170
|
deltaSeconds: seconds,
|
|
170
171
|
deltaApiCalls: apiCalls,
|
|
171
172
|
});
|
|
172
|
-
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (ok)
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
// fall through
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
try {
|
|
189
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
190
|
-
const init = {
|
|
191
|
-
method: 'POST',
|
|
192
|
-
headers,
|
|
193
|
-
body,
|
|
194
|
-
keepalive,
|
|
195
|
-
};
|
|
196
|
-
if (this.auth.usesPlatformCookie) {
|
|
197
|
-
init.credentials = 'same-origin';
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
const token = this.auth.token;
|
|
201
|
-
if (!token)
|
|
202
|
-
return;
|
|
203
|
-
headers.Authorization = `Bearer ${token}`;
|
|
204
|
-
}
|
|
205
|
-
await fetch(url, {
|
|
206
|
-
...init,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
catch {
|
|
210
|
-
// Telemetry never breaks an app.
|
|
211
|
-
}
|
|
173
|
+
// Transport lives in telemetry-transport.ts, shared with the app logger
|
|
174
|
+
// (mediated URL, bearer-vs-cookie, sendBeacon on unload). Behaviour here is
|
|
175
|
+
// unchanged: beacon is still attempted in both auth modes on the unload path,
|
|
176
|
+
// which stays best-effort in legacy-bearer mode because a beacon cannot carry
|
|
177
|
+
// the token.
|
|
178
|
+
await postTelemetry(this.auth, this.apiBase, '/v1/usage/ping', body, {
|
|
179
|
+
keepalive,
|
|
180
|
+
beacon: true,
|
|
181
|
+
});
|
|
212
182
|
}
|
|
213
183
|
isAuthenticated() {
|
|
214
184
|
return this.auth.usesPlatformCookie ? this.auth.isSignedIn === true : !!this.auth.token;
|
package/dist/usage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/dist/monitoring.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime monitoring — batches client log entries to
|
|
3
|
-
* `POST /v1/apps/:appId/logs` so app owners can inspect real user-facing
|
|
4
|
-
* failures after the fact (#105/#106).
|
|
5
|
-
*
|
|
6
|
-
* Auto-started by `initPro()` unless `monitoring.auto === false`. On start it
|
|
7
|
-
* captures uncaught `error` and `unhandledrejection` events; the SDK also feeds
|
|
8
|
-
* failed platform operations (e.g. `app.actions.call`) in via `log()`.
|
|
9
|
-
*
|
|
10
|
-
* Design (mirrors the Usage telemetry module):
|
|
11
|
-
* - **Browser-only / SSR-safe.** Every method no-ops without `window`.
|
|
12
|
-
* - **Silent.** Monitoring must never break an app — all network paths catch.
|
|
13
|
-
* - **Batched.** Entries queue and flush on an interval + on `pagehide`
|
|
14
|
-
* (sendBeacon/keepalive so the last batch survives unload).
|
|
15
|
-
* - **No secrets/PII.** Auto-capture takes only message + stack + source; the
|
|
16
|
-
* SDK never logs request bodies, SQL params, tokens, or credential values.
|
|
17
|
-
*/
|
|
18
|
-
interface AuthLike {
|
|
19
|
-
token: string | null;
|
|
20
|
-
isSignedIn?: boolean;
|
|
21
|
-
usesPlatformCookie?: boolean;
|
|
22
|
-
}
|
|
23
|
-
export interface MonitoringOptions {
|
|
24
|
-
/** Default true. Set false to disable auto-capture + auto-flush. */
|
|
25
|
-
auto?: boolean;
|
|
26
|
-
/** Build metadata attached to every entry (commit, version, …). */
|
|
27
|
-
build?: Record<string, unknown>;
|
|
28
|
-
}
|
|
29
|
-
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
30
|
-
export declare class Monitoring {
|
|
31
|
-
private readonly appId;
|
|
32
|
-
private readonly apiBase;
|
|
33
|
-
private readonly auth;
|
|
34
|
-
private readonly build?;
|
|
35
|
-
private queue;
|
|
36
|
-
private running;
|
|
37
|
-
private timer;
|
|
38
|
-
private onError;
|
|
39
|
-
private onRejection;
|
|
40
|
-
private onPageHide;
|
|
41
|
-
constructor(appId: string, apiBase: string, auth: AuthLike, build?: Record<string, unknown> | undefined);
|
|
42
|
-
/** Attach auto-capture + periodic flush. Idempotent. */
|
|
43
|
-
start(): void;
|
|
44
|
-
/** Detach handlers + stop flushing. Idempotent. Does not flush. */
|
|
45
|
-
stop(): void;
|
|
46
|
-
/** Queue a log entry. Cheap; no network until the next flush. */
|
|
47
|
-
log(level: LogLevel, category: string, message: string, data?: Record<string, unknown>): void;
|
|
48
|
-
error(category: string, message: string, data?: Record<string, unknown>): void;
|
|
49
|
-
warn(category: string, message: string, data?: Record<string, unknown>): void;
|
|
50
|
-
info(category: string, message: string, data?: Record<string, unknown>): void;
|
|
51
|
-
/** Log a caught exception with its stack. */
|
|
52
|
-
capture(err: unknown, category?: string): void;
|
|
53
|
-
/** Send queued entries. `keepalive` for page-close paths (sendBeacon). */
|
|
54
|
-
flush(keepalive?: boolean): void;
|
|
55
|
-
private isAuthenticated;
|
|
56
|
-
}
|
|
57
|
-
export {};
|
|
58
|
-
//# sourceMappingURL=monitoring.d.ts.map
|
package/dist/monitoring.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"monitoring.d.ts","sourceRoot":"","sources":["../src/monitoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAsB3D,qBAAa,UAAU;IASnB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IAXzB,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,WAAW,CAAqD;IACxE,OAAO,CAAC,UAAU,CAA6B;gBAG5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,EACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;IAGlD,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAqBb,mEAAmE;IACnE,IAAI,IAAI,IAAI;IAYZ,iEAAiE;IACjE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAc7F,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAC9E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAC7E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAE7E,6CAA6C;IAC7C,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,SAAY,GAAG,IAAI;IAKjD,0EAA0E;IAC1E,KAAK,CAAC,SAAS,UAAQ,GAAG,IAAI;IA6B9B,OAAO,CAAC,eAAe;CAGxB"}
|