@lib-acr/browser 0.0.0-stage → 0.0.2
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/LICENSE +21 -0
- package/README.md +113 -2
- package/dist/cjs/browser-acr.js +600 -0
- package/dist/cjs/browser-acr.js.map +1 -0
- package/dist/cjs/captured.js +19 -0
- package/dist/cjs/captured.js.map +1 -0
- package/dist/cjs/control/command-runner.js +289 -0
- package/dist/cjs/control/command-runner.js.map +1 -0
- package/dist/cjs/control/ui.js +277 -0
- package/dist/cjs/control/ui.js.map +1 -0
- package/dist/cjs/device.js +54 -0
- package/dist/cjs/device.js.map +1 -0
- package/dist/cjs/fetch-tracker.js +63 -0
- package/dist/cjs/fetch-tracker.js.map +1 -0
- package/dist/cjs/identity.js +120 -0
- package/dist/cjs/identity.js.map +1 -0
- package/dist/cjs/index.js +73 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/sdk-info.js +6 -0
- package/dist/cjs/sdk-info.js.map +1 -0
- package/dist/cjs/url.js +31 -0
- package/dist/cjs/url.js.map +1 -0
- package/dist/cjs/web-vitals.js +160 -0
- package/dist/cjs/web-vitals.js.map +1 -0
- package/dist/esm/browser-acr.js +595 -0
- package/dist/esm/browser-acr.js.map +1 -0
- package/dist/esm/captured.js +15 -0
- package/dist/esm/captured.js.map +1 -0
- package/dist/esm/control/command-runner.js +284 -0
- package/dist/esm/control/command-runner.js.map +1 -0
- package/dist/esm/control/ui.js +272 -0
- package/dist/esm/control/ui.js.map +1 -0
- package/dist/esm/device.js +50 -0
- package/dist/esm/device.js.map +1 -0
- package/dist/esm/fetch-tracker.js +60 -0
- package/dist/esm/fetch-tracker.js.map +1 -0
- package/dist/esm/identity.js +112 -0
- package/dist/esm/identity.js.map +1 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/sdk-info.js +3 -0
- package/dist/esm/sdk-info.js.map +1 -0
- package/dist/esm/url.js +27 -0
- package/dist/esm/url.js.map +1 -0
- package/dist/esm/web-vitals.js +156 -0
- package/dist/esm/web-vitals.js.map +1 -0
- package/dist/types/browser-acr.d.ts +142 -0
- package/dist/types/captured.d.ts +4 -0
- package/dist/types/control/command-runner.d.ts +57 -0
- package/dist/types/control/ui.d.ts +50 -0
- package/dist/types/device.d.ts +24 -0
- package/dist/types/fetch-tracker.d.ts +15 -0
- package/dist/types/identity.d.ts +48 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/sdk-info.d.ts +4 -0
- package/dist/types/url.d.ts +10 -0
- package/dist/types/web-vitals.d.ts +50 -0
- package/package.json +40 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Application Control Room
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,114 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @lib-acr/browser
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Browser SDK: uncaught errors and unhandled rejections, page views (including client-side route changes), fetch timing, Core Web Vitals, sessions and anonymous visitor ids. It accepts publishable keys only and refuses a secret key.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lib-acr/browser
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { BrowserACR } from '@lib-acr/browser';
|
|
15
|
+
|
|
16
|
+
const acr = new BrowserACR({
|
|
17
|
+
apiKey: 'acr_live_…', // publishable key, restricted to your origins
|
|
18
|
+
endpoint: 'https://acr.example.com/v1',
|
|
19
|
+
appVersion: '2.3.0',
|
|
20
|
+
});
|
|
21
|
+
acr.start(); // installs listeners; call once
|
|
22
|
+
acr.identify('user_42'); // user id only; do not pass personal data
|
|
23
|
+
acr.trackEvent('product_added_to_cart', { productId: '123', price: 500 });
|
|
24
|
+
|
|
25
|
+
if (userSaysNo) acr.optOut(); // remembered on this browser; unsent telemetry is discarded
|
|
26
|
+
onLogout(() => acr.reset()); // new anonymous id and session, no user id
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Options
|
|
30
|
+
|
|
31
|
+
| Option | Default | Notes |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `minLogLevel` | `warn` | Logs below this level are dropped in the page |
|
|
34
|
+
| `activePingMinutes` | `5` | Sends `acr.active` at this interval while the tab is visible, so ACR can count live visitors. `0` turns it off |
|
|
35
|
+
| `persistQueue` | `true` | Keeps unsent telemetry (at most 200 items / 50 kB) in `localStorage['acr.queue']` when the page is hidden and sends it on the next `start()` |
|
|
36
|
+
| `sessionTimeoutMinutes` | `30` | Any tracked event, log or error counts as activity; after the timeout a new session starts with its own `session_start` |
|
|
37
|
+
| `trackErrors`, `trackPageViews`, `trackFetch`, `trackWebVitals` | `true` | Automatic collection |
|
|
38
|
+
| `respectDoNotTrack` | `true` | |
|
|
39
|
+
| `ui` | `true` | Built-in maintenance screen, announcement banner and update prompt. `false`, or `{ maintenance?, announcement?, release? }` to turn parts off |
|
|
40
|
+
| `remoteControl` | `true` | Poll the control snapshot (kill switch, maintenance, flags, commands) |
|
|
41
|
+
| `configPollIntervalMs` | `60000` | Control snapshot poll interval, at least 15 000 |
|
|
42
|
+
|
|
43
|
+
`sampleRate` is applied per session, so a sampled-in visitor is recorded completely.
|
|
44
|
+
|
|
45
|
+
## Page hide and offline
|
|
46
|
+
|
|
47
|
+
On `pagehide` and when the tab becomes hidden, every kind is sent at once with `fetch(…, { keepalive: true })`, each
|
|
48
|
+
request at most 60 kB. `navigator.sendBeacon` is not used because it cannot send the API key header. A bounded copy of
|
|
49
|
+
anything still undelivered is kept in `localStorage` and replayed on the next visit; items keep their ids, so the API
|
|
50
|
+
drops duplicates.
|
|
51
|
+
|
|
52
|
+
## Entry point
|
|
53
|
+
|
|
54
|
+
This package re-exports the shared types and helpers of `@lib-acr/core` (for example `Attributes`, `LogLevel`,
|
|
55
|
+
`redactAttributes`), but not `AcrClient`, `HttpTransport` or `resolveConfig`: those accept a secret key and do not
|
|
56
|
+
belong in browser code.
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
Query strings and fragments are never recorded, and numeric or UUID path segments become `:id`. Do Not Track is respected by default. A failed `fetch` that the app does not catch is reported once (as a network error), not again as an unhandled rejection. INP is reported as the maximum interaction duration, which is an approximation of the official metric. Request and response bodies and headers are never read.
|
|
61
|
+
|
|
62
|
+
## Remote control
|
|
63
|
+
|
|
64
|
+
After `start()` the SDK polls the control snapshot (see `@lib-acr/core`) and polls again whenever the tab becomes
|
|
65
|
+
visible or the device comes back online. It acts on the snapshot as follows:
|
|
66
|
+
|
|
67
|
+
- **Kill switch** (`sdk.enabled: false`) stops collection and flushing until it is lifted.
|
|
68
|
+
- **Maintenance:** shows a full-page maintenance screen (focus-trapped dialog with a "Check again" button). Users or
|
|
69
|
+
anonymous ids in `allowUserIds` are exempt.
|
|
70
|
+
- **Announcement:** a banner at the top while inside its `startsAt` – `endsAt` window. Dismissals are remembered per
|
|
71
|
+
id in `localStorage['acr.dismissed']`. Call `acr.dismissAnnouncement(id)` from your own UI.
|
|
72
|
+
- **Release:** when `appVersion` is below `latestVersion` or `minimumVersion`, a "new version available" prompt with a
|
|
73
|
+
Reload button appears. With `mode: "force"` and a version below `minimumVersion`, the page reloads once per tab and
|
|
74
|
+
minimum version (guarded in `sessionStorage['acr.forceReload']`), then falls back to the prompt.
|
|
75
|
+
- **Commands** run at most once per browser. Applied ids are kept in `localStorage['acr.cmds']` (the last 50). Commands
|
|
76
|
+
issued before `localStorage['acr.firstSeen']` are skipped, and so are expired ones. The id is recorded before the
|
|
77
|
+
SDK acts, then it sends `acr.command_applied` (`commandId`, `type`, `result`, `cleared`) and flushes before any reload.
|
|
78
|
+
- `clear_cache` clears the selected categories: Cache Storage, service workers, `localStorage` and `sessionStorage`
|
|
79
|
+
(every key except the SDK's own `acr.*` keys), IndexedDB (where `indexedDB.databases()` exists, otherwise the
|
|
80
|
+
result is `partial`) and cookies readable by script. HttpOnly cookies cannot be cleared by any script.
|
|
81
|
+
- `reload` with `mode: "immediate"` reloads the page; `mode: "prompt"` shows the reload prompt. A second
|
|
82
|
+
SDK-triggered reload within 30 s turns into a prompt, so reloads cannot loop.
|
|
83
|
+
|
|
84
|
+
The built-in UI is rendered inside the shadow root of one `<acr-ui>` element, so page styles do not affect it. It
|
|
85
|
+
follows `prefers-color-scheme` and inserts server text as text, never as HTML. To render your own UI:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
const acr = new BrowserACR({ apiKey, endpoint, appVersion: '2.3.0', ui: { announcement: false } }); // or ui: false
|
|
89
|
+
acr.onControlChange(({ maintenance, announcement, release, reloadRequested }) => { /* render */ });
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`remoteControl: false` turns all of this off; `configPollIntervalMs` changes the poll interval.
|
|
93
|
+
|
|
94
|
+
## Feature flags
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
if (acr.flag('new-checkout', false)) showNewCheckout();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Flags are evaluated locally for the identified user, or for the anonymous id before `identify()`, so the same browser
|
|
101
|
+
keeps the same variant. They return the fallback until the first snapshot arrives.
|
|
102
|
+
|
|
103
|
+
## Wire protocol
|
|
104
|
+
|
|
105
|
+
Every SDK sends the same protocol: `POST {endpoint}/ingest/{events|logs|errors|heartbeat}` with the `X-ACR-Api-Key`
|
|
106
|
+
header (and `X-ACR-Secret-Key` for server keys). The credential determines the app and environment. The body is
|
|
107
|
+
`{ schemaVersion: 1, sdk, items[1..500] }`.
|
|
108
|
+
Each item has a client `id`, which lets the server drop duplicates when a batch is retried.
|
|
109
|
+
|
|
110
|
+
Retries use exponential backoff with jitter for network errors, 429 and 5xx responses. Other 4xx responses are not retried.
|
|
111
|
+
Telemetry is buffered in a bounded in-memory queue. When it is full, the oldest items are dropped and counted in `stats()`.
|
|
112
|
+
SDK code never throws into the host application.
|
|
113
|
+
|
|
114
|
+
Metrics (`increment`, `gauge`, `histogram`) and traces are not yet available.
|