@fixback/sdk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/boot.d.ts +17 -3
- package/dist/breadcrumbs.d.ts +315 -32
- package/dist/dom.d.ts +7 -0
- package/dist/fixback.umd.js +19 -5
- package/dist/fixback.umd.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +2396 -1154
- package/dist/index.mjs.map +1 -1
- package/dist/init.d.ts +42 -8
- package/dist/screenshot.d.ts +37 -18
- package/dist/scrub.d.ts +5 -4
- package/dist/version.d.ts +10 -4
- package/package.json +4 -1
package/dist/init.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type IdentityInputs } from "./boot";
|
|
2
|
-
import { type BeforeBreadcrumb, type BreadcrumbLevel } from "./breadcrumbs";
|
|
2
|
+
import { type BeforeBreadcrumb, type BreadcrumbLevel, type TraceStream } from "./breadcrumbs";
|
|
3
3
|
import type { BeforeSend } from "./scrub";
|
|
4
4
|
/**
|
|
5
5
|
* The hosted Fixback API origin the SDK talks to by default. A self-hosted or
|
|
@@ -8,17 +8,39 @@ import type { BeforeSend } from "./scrub";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const DEFAULT_API_URL = "https://api.fixback.dev";
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Does `url` address one of the SDK's **own** API endpoints? Every request the SDK
|
|
12
|
+
* issues lives under two namespaces beneath the API origin: `/api/ingest/*` — boot
|
|
13
|
+
* (`bootEndpoint`, boot.ts) and feedback (`feedbackEndpoint`, submit.ts) — and
|
|
14
|
+
* `/api/invites/*` (`inviteStatusEndpoint` / `redeemEndpoint`, invite.ts).
|
|
15
|
+
*
|
|
16
|
+
* The trace's network capture ignores **only** these, never the whole origin. That
|
|
17
|
+
* distinction matters when the instrumented app and the Fixback API share an origin — a
|
|
18
|
+
* self-hosted deployment, or Fixback running its own SDK on its own dashboard — where
|
|
19
|
+
* ignoring the origin wholesale would swallow all of the app's own requests and leave the
|
|
20
|
+
* Network tab empty. When the app and the API sit on different origins (the common case)
|
|
21
|
+
* this matches nothing extra, since the app's origin is never `apiUrl`. `url` is the raw
|
|
22
|
+
* request URL — absolute for every call the SDK makes — so a prefix test over the
|
|
23
|
+
* normalised origin is exact.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isFixbackApiRequest(apiUrl: string, url: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Trace buffer tuning (spec #122 §A). These are configurable **starting points**
|
|
28
|
+
* from the grill — three per-stream ring budgets (network ≈ 100 / console ≈ 80 /
|
|
29
|
+
* breadcrumbs ≈ 40), a shared age cap (~3 min, on), and **all** console levels
|
|
30
|
+
* captured (eviction priority, not capture, keeps warn/error above the chatter) —
|
|
31
|
+
* never frozen magic numbers. Pass `false` for {@link InitOptions.trace} to disable
|
|
14
32
|
* capture entirely.
|
|
15
33
|
*/
|
|
16
34
|
export interface TraceOptions {
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Per-stream ring budgets (network / console / breadcrumbs); each stream evicts
|
|
37
|
+
* independently, so a chatty stream can't drop another's lead-up. Any stream
|
|
38
|
+
* omitted uses its default.
|
|
39
|
+
*/
|
|
40
|
+
readonly budgets?: Partial<Record<TraceStream, number>>;
|
|
41
|
+
/** Shared age cap in ms. Defaults to ~3 min (on); pass `0` to disable age pruning. */
|
|
20
42
|
readonly maxAgeMs?: number;
|
|
21
|
-
/** Console levels captured. Defaults to
|
|
43
|
+
/** Console levels captured. Defaults to **all** levels (log/info/warn/error/assert/debug). */
|
|
22
44
|
readonly consoleLevels?: readonly BreadcrumbLevel[];
|
|
23
45
|
/** Per-crumb filter: mute a category, edit a crumb, or drop it (`null`). */
|
|
24
46
|
readonly beforeBreadcrumb?: BeforeBreadcrumb;
|
|
@@ -47,6 +69,18 @@ export interface InitOptions extends IdentityInputs {
|
|
|
47
69
|
readonly scrub?: boolean;
|
|
48
70
|
/** Trace buffer tuning, or `false` to turn the buffer off entirely. */
|
|
49
71
|
readonly trace?: TraceOptions | false;
|
|
72
|
+
/**
|
|
73
|
+
* The dev-side override of the Project's server-served capture config (spec #122
|
|
74
|
+
* §L; ticket #138). Capture is **default-on** and normally governed per-project
|
|
75
|
+
* from the dashboard, surfaced on the boot answer; set a stream here to override
|
|
76
|
+
* what the server serves for it — `{ network: false }` turns network capture off
|
|
77
|
+
* even where the Project leaves it on, and a stream left unset follows the served
|
|
78
|
+
* config. Independent of {@link trace} `false`, which turns the whole buffer off.
|
|
79
|
+
*/
|
|
80
|
+
readonly capture?: {
|
|
81
|
+
readonly console?: boolean;
|
|
82
|
+
readonly network?: boolean;
|
|
83
|
+
};
|
|
50
84
|
/**
|
|
51
85
|
* Automatic error capture — the SDK files uncaught exceptions / unhandled
|
|
52
86
|
* rejections as `source: auto` Feedback with no prompt (spec §E, ADR-0011).
|
package/dist/screenshot.d.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Client-side masked screenshot capture (spec MVP §E; ticket #54).
|
|
2
|
+
* Client-side masked screenshot capture (spec MVP §E; ticket #54; ADR-0014).
|
|
3
3
|
*
|
|
4
|
-
* The capture is **private-by-default**: input values are masked and the SDK's
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
4
|
+
* The capture is **private-by-default**: input values are masked and the SDK's own
|
|
5
|
+
* UI is excluded from a *clone* of the view **before** anything is rasterised, so no
|
|
6
|
+
* unmasked text and none of Fixback's chrome ever reaches the image.
|
|
7
|
+
*
|
|
8
|
+
* The rasterisation itself is delegated to `modern-screenshot` (ADR-0014): it clones
|
|
9
|
+
* the target, inlines the page's real styles **and** its fonts and images as data
|
|
10
|
+
* URIs, then draws the result through an SVG `<foreignObject>` onto a `<canvas>`.
|
|
11
|
+
* That closes the fidelity gap a hand-rolled `<foreignObject>` left open — external
|
|
12
|
+
* stylesheets, web fonts, and same-origin images now render — so the shot matches
|
|
13
|
+
* what the Reporter saw and lines up with the annotation's viewport-space marks.
|
|
14
|
+
*
|
|
15
|
+
* We keep the privacy guarantee by driving it through two of its hooks: `filter`
|
|
16
|
+
* drops Fixback's own host elements, and `onCloneNode` masks the clone's inputs —
|
|
17
|
+
* both run on the library's internal clone, before it embeds or serialises anything,
|
|
18
|
+
* so the live page is never touched and no real value reaches the raster. The backend
|
|
19
|
+
* is injectable so the pipeline (and the masking-before-capture guarantee) is testable
|
|
20
|
+
* without a real canvas, and it fails quietly: any problem resolves to `null` and the
|
|
21
|
+
* report is simply sent without a screenshot.
|
|
13
22
|
*/
|
|
14
23
|
/** The character private input content is replaced with. */
|
|
15
24
|
export declare const MASK_CHAR = "\u2022";
|
|
@@ -29,12 +38,19 @@ export interface Capture {
|
|
|
29
38
|
}
|
|
30
39
|
/** The screenshot filename extension for a {@link Capture}'s content type (defaults to `png`). */
|
|
31
40
|
export declare function extensionFor(type: string): string;
|
|
32
|
-
/**
|
|
33
|
-
|
|
41
|
+
/** How the SDK prepares a capture: exclude Fixback's UI, mask the clone's inputs. */
|
|
42
|
+
interface CaptureHooks {
|
|
43
|
+
/** Keep a node in the shot? Returns `false` for Fixback's own host elements. */
|
|
44
|
+
readonly filter: (node: Node) => boolean;
|
|
45
|
+
/** Mask private input content on the library's internal clone, pre-raster. */
|
|
46
|
+
readonly onCloneNode: (clone: Node) => void;
|
|
47
|
+
}
|
|
48
|
+
/** Turns a DOM subtree into image bytes at a given size (injectable for tests). */
|
|
49
|
+
export type CaptureBackend = (target: Element, meta: {
|
|
34
50
|
width: number;
|
|
35
51
|
height: number;
|
|
36
52
|
type: string;
|
|
37
|
-
}) => Promise<Blob | null>;
|
|
53
|
+
} & CaptureHooks) => Promise<Blob | null>;
|
|
38
54
|
/** Options for {@link captureView}. */
|
|
39
55
|
export interface CaptureOptions {
|
|
40
56
|
/** The element to capture. Defaults to the document element (the full view). */
|
|
@@ -43,12 +59,15 @@ export interface CaptureOptions {
|
|
|
43
59
|
readonly win?: Window;
|
|
44
60
|
/** Output content type. Defaults to `image/png`. */
|
|
45
61
|
readonly type?: string;
|
|
46
|
-
/** Override the raster
|
|
47
|
-
readonly
|
|
62
|
+
/** Override the raster backend (the default is `modern-screenshot`). */
|
|
63
|
+
readonly capture?: CaptureBackend;
|
|
48
64
|
}
|
|
49
65
|
/**
|
|
50
|
-
* Capture the current view as a masked screenshot.
|
|
51
|
-
*
|
|
52
|
-
*
|
|
66
|
+
* Capture the current view as a masked screenshot. Delegates the raster to the
|
|
67
|
+
* backend ({@link captureViaModernScreenshot} by default), which excludes the SDK's
|
|
68
|
+
* own UI and masks input values on its internal clone — **before** it embeds or
|
|
69
|
+
* serialises anything — then returns the image bytes, or `null` if capture wasn't
|
|
70
|
+
* possible.
|
|
53
71
|
*/
|
|
54
72
|
export declare function captureView(options?: CaptureOptions): Promise<Capture | null>;
|
|
73
|
+
export {};
|
package/dist/scrub.d.ts
CHANGED
|
@@ -35,10 +35,11 @@ export interface BeforeSendOptions {
|
|
|
35
35
|
export declare function redactPii(text: string): string;
|
|
36
36
|
/**
|
|
37
37
|
* Strip the sensitive parts of a URL: userinfo credentials
|
|
38
|
-
* (`scheme://user:pass@host`), the entire query string,
|
|
39
|
-
* fragment (one that carries `key=value`)
|
|
40
|
-
*
|
|
41
|
-
* throw.
|
|
38
|
+
* (`scheme://user:pass@host`), the entire query string, a token-bearing
|
|
39
|
+
* fragment (one that carries `key=value`), and PII (emails, long digit runs) in
|
|
40
|
+
* the **path segments** (#139). Plain hash routes (`#/checkout`) are kept. Works
|
|
41
|
+
* on absolute and relative URLs alike, with no dependency and no throw. The host
|
|
42
|
+
* (authority) is never redacted — only the path and any surviving fragment route.
|
|
42
43
|
*/
|
|
43
44
|
export declare function scrubUrl(url: string): string;
|
|
44
45
|
/**
|
package/dist/version.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The SDK's own version string, reported to ingest as `environment.sdkVersion`
|
|
3
|
-
* (spec MVP §B/§E). Kept as
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* (spec MVP §B/§E). Kept as an inlined constant rather than a runtime `package.json`
|
|
4
|
+
* import, so the published bundle stays a single self-contained file.
|
|
5
|
+
*
|
|
6
|
+
* It must equal `package.json`'s `version`. Two things keep it there: the Changesets
|
|
7
|
+
* `version` step syncs it automatically (`scripts/sync-sdk-version.mjs`, wired into
|
|
8
|
+
* `version-packages`), and `version.test.ts` fails the build if the two ever drift —
|
|
9
|
+
* so a stale dogfood version (the SDK reporting an old number on our own dashboard)
|
|
10
|
+
* can't slip through. Do not hand-edit this line to a value other than
|
|
11
|
+
* `package.json`'s version.
|
|
6
12
|
*/
|
|
7
|
-
export declare const SDK_VERSION = "0.
|
|
13
|
+
export declare const SDK_VERSION = "0.3.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fixback/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The Fixback capture SDK — a boot-gated, self-isolating on-page feedback launcher.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -40,6 +40,9 @@
|
|
|
40
40
|
"publishConfig": {
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"modern-screenshot": "^4.7.0"
|
|
45
|
+
},
|
|
43
46
|
"devDependencies": {
|
|
44
47
|
"jsdom": "^30.0.1",
|
|
45
48
|
"typescript": "5.9.3",
|