@fixback/expo 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 +72 -8
- package/dist/FeedbackModal.d.ts +10 -2
- package/dist/FeedbackModal.js +84 -36
- package/dist/FeedbackModal.js.map +1 -0
- package/dist/FixbackProvider.d.ts +12 -0
- package/dist/FixbackProvider.js +46 -23
- package/dist/FixbackProvider.js.map +1 -0
- package/dist/adapters.js +73 -23
- package/dist/adapters.js.map +1 -0
- package/dist/breadcrumbs.d.ts +21 -222
- package/dist/breadcrumbs.js +45 -605
- package/dist/breadcrumbs.js.map +1 -0
- package/dist/client.d.ts +65 -67
- package/dist/client.js +288 -151
- package/dist/client.js.map +1 -0
- package/dist/connect.d.ts +60 -0
- package/dist/connect.js +63 -0
- package/dist/connect.js.map +1 -0
- package/dist/error-capture.d.ts +28 -78
- package/dist/error-capture.js +76 -294
- package/dist/error-capture.js.map +1 -0
- package/dist/http.d.ts +10 -25
- package/dist/http.js +15 -12
- package/dist/http.js.map +1 -0
- package/dist/identity.d.ts +11 -11
- package/dist/identity.js +23 -28
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +22 -5
- package/dist/index.js.map +1 -0
- package/dist/origin.d.ts +21 -0
- package/dist/origin.js +45 -0
- package/dist/origin.js.map +1 -0
- package/dist/package.json +3 -0
- package/dist/report.d.ts +28 -63
- package/dist/report.js +33 -25
- package/dist/report.js.map +1 -0
- package/dist/reporter-session-store.d.ts +27 -0
- package/dist/reporter-session-store.js +53 -0
- package/dist/reporter-session-store.js.map +1 -0
- package/dist/shake.d.ts +26 -0
- package/dist/shake.js +32 -7
- package/dist/shake.js.map +1 -0
- package/dist/submit.d.ts +21 -12
- package/dist/submit.js +24 -41
- package/dist/submit.js.map +1 -0
- package/dist/tokens.js +5 -1
- package/dist/tokens.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +5 -1
- package/dist/version.js.map +1 -0
- package/package.json +14 -7
- package/dist/auto-report-backoff.d.ts +0 -42
- package/dist/auto-report-backoff.js +0 -67
- package/dist/boot.d.ts +0 -65
- package/dist/boot.js +0 -60
- package/dist/scrub.d.ts +0 -55
- package/dist/scrub.js +0 -184
package/dist/http.d.ts
CHANGED
|
@@ -1,31 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The **`FormData` slice** the multipart submission uses — the one HTTP shape that
|
|
3
|
+
* is genuinely React Native's own.
|
|
3
4
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
5
|
+
* The `fetch` surface (`FetchLike`, `FetchRequestInit`, `FetchResponseLike`,
|
|
6
|
+
* `resolveFetch`) is shared with the browser and Node SDKs and lives in
|
|
7
|
+
* `@fixback/sdk-core` (ADR-0028). What stays here is the part that differs:
|
|
8
|
+
* React Native's `FormData` accepts `{ uri, name, type }` objects as file parts —
|
|
9
|
+
* that is how the screenshot travels, since there is no `Blob` screenshot on
|
|
10
|
+
* mobile. The package typechecks without the DOM lib (React Native is not a
|
|
11
|
+
* browser), so the constructor is read off `globalThis` defensively; tests inject
|
|
12
|
+
* fakes through the same seam.
|
|
9
13
|
*/
|
|
10
|
-
/** The response slice `boot`/`submit` read: status, ok, headers, JSON body. */
|
|
11
|
-
export interface FetchResponseLike {
|
|
12
|
-
readonly ok: boolean;
|
|
13
|
-
readonly status: number;
|
|
14
|
-
readonly headers?: {
|
|
15
|
-
get(name: string): string | null;
|
|
16
|
-
} | null;
|
|
17
|
-
json(): Promise<unknown>;
|
|
18
|
-
}
|
|
19
|
-
/** The request init the SDK sends — method, plain headers, and a body. */
|
|
20
|
-
export interface FetchRequestInit {
|
|
21
|
-
readonly method: string;
|
|
22
|
-
readonly headers?: Record<string, string>;
|
|
23
|
-
readonly body?: unknown;
|
|
24
|
-
}
|
|
25
|
-
/** A `fetch`-shaped function, injectable for tests. */
|
|
26
|
-
export type FetchLike = (url: string, init: FetchRequestInit) => Promise<FetchResponseLike>;
|
|
27
|
-
/** React Native's global `fetch`, when present. Bound so `this` never matters. */
|
|
28
|
-
export declare function globalFetch(): FetchLike | undefined;
|
|
29
14
|
/**
|
|
30
15
|
* The `FormData` slice the submission uses. React Native's implementation
|
|
31
16
|
* accepts `{ uri, name, type }` objects as file parts — that is how the
|
package/dist/http.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* The **`FormData` slice** the multipart submission uses — the one HTTP shape that
|
|
4
|
+
* is genuinely React Native's own.
|
|
3
5
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
6
|
+
* The `fetch` surface (`FetchLike`, `FetchRequestInit`, `FetchResponseLike`,
|
|
7
|
+
* `resolveFetch`) is shared with the browser and Node SDKs and lives in
|
|
8
|
+
* `@fixback/sdk-core` (ADR-0028). What stays here is the part that differs:
|
|
9
|
+
* React Native's `FormData` accepts `{ uri, name, type }` objects as file parts —
|
|
10
|
+
* that is how the screenshot travels, since there is no `Blob` screenshot on
|
|
11
|
+
* mobile. The package typechecks without the DOM lib (React Native is not a
|
|
12
|
+
* browser), so the constructor is read off `globalThis` defensively; tests inject
|
|
13
|
+
* fakes through the same seam.
|
|
9
14
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const g = globalThis;
|
|
13
|
-
return typeof g.fetch === "function" ? g.fetch.bind(globalThis) : undefined;
|
|
14
|
-
}
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.globalFormData = globalFormData;
|
|
15
17
|
/** React Native's global `FormData` constructor, when present. */
|
|
16
|
-
|
|
18
|
+
function globalFormData() {
|
|
17
19
|
const g = globalThis;
|
|
18
20
|
const ctor = g.FormData;
|
|
19
21
|
return typeof ctor === "function" ? () => new ctor() : undefined;
|
|
20
22
|
}
|
|
23
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAeH,wCAIC;AALD,kEAAkE;AAClE,SAAgB,cAAc;IAC5B,MAAM,CAAC,GAAG,UAAmD,CAAC;IAC9D,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC;IACxB,OAAO,OAAO,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC"}
|
package/dist/identity.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Public Reporter's
|
|
3
|
-
*
|
|
2
|
+
* The Public Reporter's anonymous id on React Native — the **storage binding**
|
|
3
|
+
* only.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* The key and the id generator are shared with every other SDK
|
|
6
|
+
* (`@fixback/sdk-core`, ADR-0028), so a Fixback anonymous id looks the same across
|
|
7
|
+
* clients. What differs, and so lives here, is persistence: React Native's
|
|
8
|
+
* AsyncStorage is asynchronous, where a browser's `localStorage` is not.
|
|
9
|
+
*
|
|
10
|
+
* Persistence is best-effort: if storage is unavailable or failing, we fall back to
|
|
11
|
+
* an ephemeral id rather than throw — the SDK must never disturb the host app.
|
|
11
12
|
*/
|
|
13
|
+
import { ANONYMOUS_ID_STORAGE_KEY, generateAnonymousId } from "@fixback/sdk-core";
|
|
14
|
+
export { ANONYMOUS_ID_STORAGE_KEY, generateAnonymousId };
|
|
12
15
|
/** The async storage slice the SDK uses — AsyncStorage-shaped, injectable. */
|
|
13
16
|
export interface StorageLike {
|
|
14
17
|
getItem(key: string): Promise<string | null>;
|
|
15
18
|
setItem(key: string, value: string): Promise<void>;
|
|
16
19
|
}
|
|
17
|
-
export declare const ANONYMOUS_ID_STORAGE_KEY = "fixback.anonymousId";
|
|
18
|
-
/** A random id: a UUID where the platform offers one, else a compact fallback. */
|
|
19
|
-
export declare function generateAnonymousId(): string;
|
|
20
20
|
/**
|
|
21
21
|
* Return this device's anonymous id, creating and persisting one on first use.
|
|
22
22
|
* Any storage failure — absent module, quota, corrupted value — yields an
|
package/dist/identity.js
CHANGED
|
@@ -1,46 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
|
-
* The Public Reporter's
|
|
3
|
-
*
|
|
3
|
+
* The Public Reporter's anonymous id on React Native — the **storage binding**
|
|
4
|
+
* only.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* The key and the id generator are shared with every other SDK
|
|
7
|
+
* (`@fixback/sdk-core`, ADR-0028), so a Fixback anonymous id looks the same across
|
|
8
|
+
* clients. What differs, and so lives here, is persistence: React Native's
|
|
9
|
+
* AsyncStorage is asynchronous, where a browser's `localStorage` is not.
|
|
10
|
+
*
|
|
11
|
+
* Persistence is best-effort: if storage is unavailable or failing, we fall back to
|
|
12
|
+
* an ephemeral id rather than throw — the SDK must never disturb the host app.
|
|
11
13
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return c.randomUUID();
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
// Fall through to the compact fallback.
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return `fb-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
25
|
-
}
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.generateAnonymousId = exports.ANONYMOUS_ID_STORAGE_KEY = void 0;
|
|
16
|
+
exports.ensureAnonymousId = ensureAnonymousId;
|
|
17
|
+
const sdk_core_1 = require("@fixback/sdk-core");
|
|
18
|
+
Object.defineProperty(exports, "ANONYMOUS_ID_STORAGE_KEY", { enumerable: true, get: function () { return sdk_core_1.ANONYMOUS_ID_STORAGE_KEY; } });
|
|
19
|
+
Object.defineProperty(exports, "generateAnonymousId", { enumerable: true, get: function () { return sdk_core_1.generateAnonymousId; } });
|
|
26
20
|
/**
|
|
27
21
|
* Return this device's anonymous id, creating and persisting one on first use.
|
|
28
22
|
* Any storage failure — absent module, quota, corrupted value — yields an
|
|
29
23
|
* ephemeral id for this session instead of an error.
|
|
30
24
|
*/
|
|
31
|
-
|
|
25
|
+
async function ensureAnonymousId(storage) {
|
|
32
26
|
if (!storage)
|
|
33
|
-
return generateAnonymousId();
|
|
27
|
+
return (0, sdk_core_1.generateAnonymousId)();
|
|
34
28
|
try {
|
|
35
|
-
const existing = await storage.getItem(ANONYMOUS_ID_STORAGE_KEY);
|
|
29
|
+
const existing = await storage.getItem(sdk_core_1.ANONYMOUS_ID_STORAGE_KEY);
|
|
36
30
|
if (typeof existing === "string" && existing.length > 0)
|
|
37
31
|
return existing;
|
|
38
|
-
const id = generateAnonymousId();
|
|
39
|
-
await storage.setItem(ANONYMOUS_ID_STORAGE_KEY, id);
|
|
32
|
+
const id = (0, sdk_core_1.generateAnonymousId)();
|
|
33
|
+
await storage.setItem(sdk_core_1.ANONYMOUS_ID_STORAGE_KEY, id);
|
|
40
34
|
return id;
|
|
41
35
|
}
|
|
42
36
|
catch {
|
|
43
37
|
// Storage blocked or absent — an ephemeral id keeps this boot working.
|
|
44
|
-
return generateAnonymousId();
|
|
38
|
+
return (0, sdk_core_1.generateAnonymousId)();
|
|
45
39
|
}
|
|
46
40
|
}
|
|
41
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAkBH,8CAcC;AA9BD,gDAAkF;AAGzE,yGAHA,mCAAwB,OAGA;AAAE,oGAHA,8BAAmB,OAGA;AAQtD;;;;GAIG;AACI,KAAK,UAAU,iBAAiB,CACrC,OAAuC;IAEvC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAA,8BAAmB,GAAE,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,mCAAwB,CAAC,CAAC;QACjE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,QAAQ,CAAC;QACzE,MAAM,EAAE,GAAG,IAAA,8BAAmB,GAAE,CAAC;QACjC,MAAM,OAAO,CAAC,OAAO,CAAC,mCAAwB,EAAE,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,IAAA,8BAAmB,GAAE,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
* @fixback/expo — the Fixback capture SDK for Expo / React Native apps.
|
|
3
3
|
*
|
|
4
4
|
* Shake the device to report feedback with trace Evidence; uncaught errors
|
|
5
|
-
* report themselves. Spec 0004; decision record ADR-0021.
|
|
5
|
+
* report themselves. Spec 0004; decision record ADR-0021. The runtime-agnostic
|
|
6
|
+
* half (trace buffer, crumb builders, scrubbing, fingerprinting, boot contract)
|
|
7
|
+
* is `@fixback/sdk-core` (ADR-0028) and re-exported here, so a host app imports
|
|
8
|
+
* everything from one package.
|
|
6
9
|
*/
|
|
7
10
|
export { Fixback, FixbackProvider, useFixback, type FixbackHandle, type FixbackProviderProps, } from "./FixbackProvider";
|
|
8
|
-
export { canonicalizeOrigin, createFixbackClient, DEFAULT_API_URL, DEFAULT_SHAKE_SAMPLE_INTERVAL_MS, type ComposerContext, type ComposerDraft, type FixbackAdapters, type FixbackClient, type FixbackOptions, type FixbackStatus, type ShakeOptions, } from "./client";
|
|
9
|
-
export type { BootAnswer, CaptureConfig, IdentityInputs, ProjectGate, ReporterTier, } from "
|
|
11
|
+
export { canonicalizeOrigin, createFixbackClient, DEFAULT_API_URL, DEFAULT_SHAKE_SAMPLE_INTERVAL_MS, type ComposerContext, type ComposerDraft, type FixbackAdapters, type FixbackClient, type FixbackOptions, type FixbackStatus, type ResolvedShakeConfig, type ShakeOptions, } from "./client";
|
|
12
|
+
export type { BeforeBreadcrumb, BeforeSend, BootAnswer, Breadcrumb, BreadcrumbCategory, BreadcrumbLevel, CaptureConfig, CaptureToggles, CommonInitOptions, IdentityInputs, ProjectGate, ReporterIdentity, ReporterTier, } from "@fixback/sdk-core";
|
|
10
13
|
export type { CaptureEnvironment, FeedbackSource, ReportContent, } from "./report";
|
|
11
|
-
export type { Breadcrumb, BreadcrumbCategory, BreadcrumbLevel, BeforeBreadcrumb, } from "./breadcrumbs";
|
|
12
|
-
export type { BeforeSend } from "./scrub";
|
|
13
14
|
export { createShakeDetector, DEFAULT_SHAKE_TUNING, type ShakeDetector, type ShakeSample, type ShakeTuning, } from "./shake";
|
|
14
15
|
export type { RecordedFeedback, ScreenshotFile, SubmitResult, } from "./submit";
|
|
15
16
|
export { EXPO_SDK_VERSION } from "./version";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* @fixback/expo — the Fixback capture SDK for Expo / React Native apps.
|
|
3
4
|
*
|
|
4
5
|
* Shake the device to report feedback with trace Evidence; uncaught errors
|
|
5
|
-
* report themselves. Spec 0004; decision record ADR-0021.
|
|
6
|
+
* report themselves. Spec 0004; decision record ADR-0021. The runtime-agnostic
|
|
7
|
+
* half (trace buffer, crumb builders, scrubbing, fingerprinting, boot contract)
|
|
8
|
+
* is `@fixback/sdk-core` (ADR-0028) and re-exported here, so a host app imports
|
|
9
|
+
* everything from one package.
|
|
6
10
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EXPO_SDK_VERSION = exports.DEFAULT_SHAKE_TUNING = exports.createShakeDetector = exports.DEFAULT_SHAKE_SAMPLE_INTERVAL_MS = exports.DEFAULT_API_URL = exports.createFixbackClient = exports.canonicalizeOrigin = exports.useFixback = exports.FixbackProvider = exports.Fixback = void 0;
|
|
13
|
+
var FixbackProvider_1 = require("./FixbackProvider");
|
|
14
|
+
Object.defineProperty(exports, "Fixback", { enumerable: true, get: function () { return FixbackProvider_1.Fixback; } });
|
|
15
|
+
Object.defineProperty(exports, "FixbackProvider", { enumerable: true, get: function () { return FixbackProvider_1.FixbackProvider; } });
|
|
16
|
+
Object.defineProperty(exports, "useFixback", { enumerable: true, get: function () { return FixbackProvider_1.useFixback; } });
|
|
17
|
+
var client_1 = require("./client");
|
|
18
|
+
Object.defineProperty(exports, "canonicalizeOrigin", { enumerable: true, get: function () { return client_1.canonicalizeOrigin; } });
|
|
19
|
+
Object.defineProperty(exports, "createFixbackClient", { enumerable: true, get: function () { return client_1.createFixbackClient; } });
|
|
20
|
+
Object.defineProperty(exports, "DEFAULT_API_URL", { enumerable: true, get: function () { return client_1.DEFAULT_API_URL; } });
|
|
21
|
+
Object.defineProperty(exports, "DEFAULT_SHAKE_SAMPLE_INTERVAL_MS", { enumerable: true, get: function () { return client_1.DEFAULT_SHAKE_SAMPLE_INTERVAL_MS; } });
|
|
22
|
+
var shake_1 = require("./shake");
|
|
23
|
+
Object.defineProperty(exports, "createShakeDetector", { enumerable: true, get: function () { return shake_1.createShakeDetector; } });
|
|
24
|
+
Object.defineProperty(exports, "DEFAULT_SHAKE_TUNING", { enumerable: true, get: function () { return shake_1.DEFAULT_SHAKE_TUNING; } });
|
|
25
|
+
var version_1 = require("./version");
|
|
26
|
+
Object.defineProperty(exports, "EXPO_SDK_VERSION", { enumerable: true, get: function () { return version_1.EXPO_SDK_VERSION; } });
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,qDAM2B;AALzB,0GAAA,OAAO,OAAA;AACP,kHAAA,eAAe,OAAA;AACf,6GAAA,UAAU,OAAA;AAKZ,mCAakB;AAZhB,4GAAA,kBAAkB,OAAA;AAClB,6GAAA,mBAAmB,OAAA;AACnB,yGAAA,eAAe,OAAA;AACf,0HAAA,gCAAgC,OAAA;AAkClC,iCAMiB;AALf,4GAAA,mBAAmB,OAAA;AACnB,6GAAA,oBAAoB,OAAA;AAYtB,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA"}
|
package/dist/origin.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonicalizing the configured **origin** (spec 0004 §A).
|
|
3
|
+
*
|
|
4
|
+
* On the web the browser serializes the `Origin` header; here the SDK is the
|
|
5
|
+
* serializer, so it must produce exactly what the server stored. This is pure and
|
|
6
|
+
* self-contained precisely so it can be unit-tested directly, without booting a
|
|
7
|
+
* client.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Canonicalize the configured origin exactly as the server's `normalizeOrigin`
|
|
11
|
+
* does when an allowlist entry is stored (`apps/api/src/projects/origin.ts`):
|
|
12
|
+
* lowercase the scheme and host, elide default ports, and drop any userinfo,
|
|
13
|
+
* path, query, or fragment. The server compares the `Origin` header by exact
|
|
14
|
+
* string equality against those canonical rows — so without this a pasted
|
|
15
|
+
* `https://com.acme.MyApp` (bundle ids legally carry uppercase) would silently
|
|
16
|
+
* never match its own allowlist entry. Implemented without `URL` (React Native's
|
|
17
|
+
* polyfill is partial); a value that doesn't parse as an http(s) origin is kept
|
|
18
|
+
* trimmed — boot will simply refuse it. IDN hosts are not punycoded (the one
|
|
19
|
+
* divergence from the server; use the encoded form).
|
|
20
|
+
*/
|
|
21
|
+
export declare function canonicalizeOrigin(value: string): string;
|
package/dist/origin.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Canonicalizing the configured **origin** (spec 0004 §A).
|
|
4
|
+
*
|
|
5
|
+
* On the web the browser serializes the `Origin` header; here the SDK is the
|
|
6
|
+
* serializer, so it must produce exactly what the server stored. This is pure and
|
|
7
|
+
* self-contained precisely so it can be unit-tested directly, without booting a
|
|
8
|
+
* client.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.canonicalizeOrigin = canonicalizeOrigin;
|
|
12
|
+
/**
|
|
13
|
+
* Canonicalize the configured origin exactly as the server's `normalizeOrigin`
|
|
14
|
+
* does when an allowlist entry is stored (`apps/api/src/projects/origin.ts`):
|
|
15
|
+
* lowercase the scheme and host, elide default ports, and drop any userinfo,
|
|
16
|
+
* path, query, or fragment. The server compares the `Origin` header by exact
|
|
17
|
+
* string equality against those canonical rows — so without this a pasted
|
|
18
|
+
* `https://com.acme.MyApp` (bundle ids legally carry uppercase) would silently
|
|
19
|
+
* never match its own allowlist entry. Implemented without `URL` (React Native's
|
|
20
|
+
* polyfill is partial); a value that doesn't parse as an http(s) origin is kept
|
|
21
|
+
* trimmed — boot will simply refuse it. IDN hosts are not punycoded (the one
|
|
22
|
+
* divergence from the server; use the encoded form).
|
|
23
|
+
*/
|
|
24
|
+
function canonicalizeOrigin(value) {
|
|
25
|
+
const trimmed = value.trim();
|
|
26
|
+
const match = trimmed.match(/^(https?):\/\/([^/?#]+)(?:[/?#].*)?$/i);
|
|
27
|
+
if (!match)
|
|
28
|
+
return trimmed.replace(/\/+$/, "");
|
|
29
|
+
const scheme = match[1].toLowerCase();
|
|
30
|
+
let authority = match[2];
|
|
31
|
+
const at = authority.lastIndexOf("@");
|
|
32
|
+
if (at >= 0)
|
|
33
|
+
authority = authority.slice(at + 1);
|
|
34
|
+
let host = authority;
|
|
35
|
+
let port;
|
|
36
|
+
const portMatch = authority.match(/^(.+):(\d+)$/);
|
|
37
|
+
if (portMatch) {
|
|
38
|
+
host = portMatch[1];
|
|
39
|
+
port = portMatch[2];
|
|
40
|
+
}
|
|
41
|
+
host = host.toLowerCase();
|
|
42
|
+
const isDefaultPort = !port || (scheme === "https" && port === "443") || (scheme === "http" && port === "80");
|
|
43
|
+
return isDefaultPort ? `${scheme}://${host}` : `${scheme}://${host}:${port}`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=origin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin.js","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAcH,gDAmBC;AA/BD;;;;;;;;;;;GAWG;AACH,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACrE,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,SAAS,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;IAC1B,MAAM,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,EAAE,IAAI,CAAC;QAAE,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACjD,IAAI,IAAI,GAAG,SAAS,CAAC;IACrB,IAAI,IAAwB,CAAC;IAC7B,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAClD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IACvB,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1B,MAAM,aAAa,GACjB,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;IAC1F,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;AAC/E,CAAC"}
|
package/dist/report.d.ts
CHANGED
|
@@ -1,63 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
2
|
+
* Assembling the ingest **feedback** content from what a Reporter composed in the
|
|
3
|
+
* mobile composer, plus the device-side environment capture.
|
|
4
|
+
*
|
|
5
|
+
* The wire shapes themselves — `ReportContent`, `CaptureEnvironment`,
|
|
6
|
+
* `FeedbackSource` — live in `@fixback/sdk-core` (ADR-0028), so the mobile SDK
|
|
7
|
+
* speaks the *same* contract as the browser and backend rather than a vendored
|
|
8
|
+
* subset of it. This module re-exports them for the SDK's public surface and holds
|
|
9
|
+
* only the mobile-specific assembly: reading the environment off the device, and
|
|
10
|
+
* clamping the free-form reporter display fields.
|
|
11
|
+
*
|
|
12
|
+
* The mobile slice carries no `annotation` (element picking and drawing are web-only
|
|
13
|
+
* today, spec 0004 §G); every content field is optional on the server, so the
|
|
14
|
+
* payload simply omits it.
|
|
7
15
|
*/
|
|
8
|
-
import type { Breadcrumb } from "
|
|
9
|
-
|
|
10
|
-
* Where a Feedback came from — a human in the composer (`reporter`, the
|
|
11
|
-
* default) or the SDK's automatic error capture (`error`). Mirrors the server's
|
|
12
|
-
* `FEEDBACK_SOURCES`; the server derives trust independently.
|
|
13
|
-
*/
|
|
14
|
-
export type FeedbackSource = "reporter" | "error";
|
|
15
|
-
/** The capture environment recorded alongside a report. */
|
|
16
|
-
export interface CaptureEnvironment {
|
|
17
|
-
readonly viewportWidth?: number;
|
|
18
|
-
readonly viewportHeight?: number;
|
|
19
|
-
readonly browser?: string;
|
|
20
|
-
readonly sdkVersion?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* The JSON content of a feedback submission — the object serialised into the
|
|
24
|
-
* multipart `payload` part next to the `key` and identity evidence. Every
|
|
25
|
-
* field is optional: none of it feeds the server's trust decision. The
|
|
26
|
-
* screenshot is a separate binary part, never part of this JSON.
|
|
27
|
-
*/
|
|
28
|
-
export interface ReportContent {
|
|
29
|
-
readonly comment?: string;
|
|
30
|
-
/**
|
|
31
|
-
* The Reporter's self-provided display **name / email** — display only,
|
|
32
|
-
* never a trust signal; the server derives the tier from identity evidence
|
|
33
|
-
* alone and ignores these.
|
|
34
|
-
*/
|
|
35
|
-
readonly reporterName?: string;
|
|
36
|
-
readonly reporterEmail?: string;
|
|
37
|
-
/** On mobile: `<origin>/<screen>` when a screen was tracked, else the origin. */
|
|
38
|
-
readonly url?: string;
|
|
39
|
-
readonly environment?: CaptureEnvironment;
|
|
40
|
-
/** The masked breadcrumb trace buffer that rode on this report. */
|
|
41
|
-
readonly trace?: readonly Breadcrumb[];
|
|
42
|
-
/**
|
|
43
|
-
* Provenance. Omitted for a manual report — the transport stamps the
|
|
44
|
-
* `reporter` default on the wire; set to `error` by the SDK's error capture.
|
|
45
|
-
*/
|
|
46
|
-
readonly source?: FeedbackSource;
|
|
47
|
-
/** For `source: error` only — the SDK's per-session error fingerprint. */
|
|
48
|
-
readonly errorSignature?: string;
|
|
49
|
-
/** For `source: error` only — the running occurrence count within the session. */
|
|
50
|
-
readonly occurrences?: number;
|
|
51
|
-
}
|
|
16
|
+
import type { Breadcrumb, CaptureEnvironment, FeedbackSource, ReportContent } from "@fixback/sdk-core";
|
|
17
|
+
export type { CaptureEnvironment, FeedbackSource, ReportContent };
|
|
52
18
|
/** What the composer hands to {@link assembleContent} when the Reporter sends. */
|
|
53
19
|
export interface ReportDraft {
|
|
54
20
|
readonly comment?: string;
|
|
55
21
|
readonly url?: string;
|
|
56
22
|
readonly environment?: CaptureEnvironment;
|
|
57
23
|
readonly trace?: readonly Breadcrumb[];
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The deploy **Environment** the SDK was configured with (ADR-0025) —
|
|
26
|
+
* `production` / `staging` / … — distinct from the build `release` in
|
|
27
|
+
* {@link CaptureEnvironment}. Named apart from `environment` (the capture bag)
|
|
28
|
+
* to avoid the collision, exactly as the wire does.
|
|
29
|
+
*/
|
|
30
|
+
readonly deployEnvironment?: string;
|
|
61
31
|
}
|
|
62
32
|
/** What the platform adapter reads off the device for the environment. */
|
|
63
33
|
export interface EnvironmentInputs {
|
|
@@ -72,18 +42,13 @@ export interface EnvironmentInputs {
|
|
|
72
42
|
* dimension is recorded only when it is a positive number (the server rejects
|
|
73
43
|
* `0` via `int().positive()`); the `browser` field — the server's free-form
|
|
74
44
|
* client string — carries a `react-native <os>` description.
|
|
45
|
+
*
|
|
46
|
+
* The **Release** (#117, ADR-0024) is stamped here too, already validated by the
|
|
47
|
+
* client (`normaliseRelease`). Without it a mobile build's captured frames cannot
|
|
48
|
+
* be matched against the sourcemaps `fixback sourcemaps upload` shipped for that
|
|
49
|
+
* build, so symbolication would silently do nothing.
|
|
75
50
|
*/
|
|
76
|
-
export declare function collectEnvironment(inputs: EnvironmentInputs, sdkVersion: string): CaptureEnvironment;
|
|
77
|
-
/**
|
|
78
|
-
* The server's hard bounds on the display-only reporter fields
|
|
79
|
-
* (`feedbackContentBody` in `apps/api/src/ingest/ingest.controller.ts`). An
|
|
80
|
-
* over-long value fails the whole submission with a 400 there, and unlike the
|
|
81
|
-
* web SDK — whose onboarding input is the source — these arrive as free-form
|
|
82
|
-
* init options, so the client clamps rather than lets one oversized display
|
|
83
|
-
* string swallow every report.
|
|
84
|
-
*/
|
|
85
|
-
export declare const MAX_REPORTER_NAME_LENGTH = 200;
|
|
86
|
-
export declare const MAX_REPORTER_EMAIL_LENGTH = 320;
|
|
51
|
+
export declare function collectEnvironment(inputs: EnvironmentInputs, sdkVersion: string, release?: string): CaptureEnvironment;
|
|
87
52
|
/**
|
|
88
53
|
* Assemble the ingest content from what the Reporter composed. Empty pieces
|
|
89
54
|
* are dropped rather than sent as blanks: a whitespace-only comment or an
|
package/dist/report.js
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Assembling the ingest **feedback** content from what a Reporter composed in the
|
|
4
|
+
* mobile composer, plus the device-side environment capture.
|
|
5
|
+
*
|
|
6
|
+
* The wire shapes themselves — `ReportContent`, `CaptureEnvironment`,
|
|
7
|
+
* `FeedbackSource` — live in `@fixback/sdk-core` (ADR-0028), so the mobile SDK
|
|
8
|
+
* speaks the *same* contract as the browser and backend rather than a vendored
|
|
9
|
+
* subset of it. This module re-exports them for the SDK's public surface and holds
|
|
10
|
+
* only the mobile-specific assembly: reading the environment off the device, and
|
|
11
|
+
* clamping the free-form reporter display fields.
|
|
12
|
+
*
|
|
13
|
+
* The mobile slice carries no `annotation` (element picking and drawing are web-only
|
|
14
|
+
* today, spec 0004 §G); every content field is optional on the server, so the
|
|
15
|
+
* payload simply omits it.
|
|
7
16
|
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.collectEnvironment = collectEnvironment;
|
|
19
|
+
exports.assembleContent = assembleContent;
|
|
8
20
|
/**
|
|
9
21
|
* Build the capture environment from what the adapter read off the device. A
|
|
10
22
|
* dimension is recorded only when it is a positive number (the server rejects
|
|
11
23
|
* `0` via `int().positive()`); the `browser` field — the server's free-form
|
|
12
24
|
* client string — carries a `react-native <os>` description.
|
|
25
|
+
*
|
|
26
|
+
* The **Release** (#117, ADR-0024) is stamped here too, already validated by the
|
|
27
|
+
* client (`normaliseRelease`). Without it a mobile build's captured frames cannot
|
|
28
|
+
* be matched against the sourcemaps `fixback sourcemaps upload` shipped for that
|
|
29
|
+
* build, so symbolication would silently do nothing.
|
|
13
30
|
*/
|
|
14
|
-
|
|
31
|
+
function collectEnvironment(inputs, sdkVersion, release) {
|
|
15
32
|
const env = {};
|
|
16
33
|
const width = inputs.windowWidth;
|
|
17
34
|
if (typeof width === "number" && width > 0)
|
|
@@ -24,44 +41,35 @@ export function collectEnvironment(inputs, sdkVersion) {
|
|
|
24
41
|
env.browser = os ? `react-native ${os}` : "react-native";
|
|
25
42
|
if (sdkVersion.length > 0)
|
|
26
43
|
env.sdkVersion = sdkVersion;
|
|
44
|
+
if (release && release.length > 0)
|
|
45
|
+
env.release = release;
|
|
27
46
|
return env;
|
|
28
47
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* over-long value fails the whole submission with a 400 there, and unlike the
|
|
33
|
-
* web SDK — whose onboarding input is the source — these arrive as free-form
|
|
34
|
-
* init options, so the client clamps rather than lets one oversized display
|
|
35
|
-
* string swallow every report.
|
|
36
|
-
*/
|
|
37
|
-
export const MAX_REPORTER_NAME_LENGTH = 200;
|
|
38
|
-
export const MAX_REPORTER_EMAIL_LENGTH = 320;
|
|
48
|
+
// The self-provided reporter display name / email are gone (ADR-0032): a Reporter is an
|
|
49
|
+
// Account, so a name and email come from the signed-in `user`. The Expo Connect flow
|
|
50
|
+
// that supplies the Account lands in ticket #251.
|
|
39
51
|
/**
|
|
40
52
|
* Assemble the ingest content from what the Reporter composed. Empty pieces
|
|
41
53
|
* are dropped rather than sent as blanks: a whitespace-only comment or an
|
|
42
54
|
* empty environment is simply omitted, so the payload carries only what was
|
|
43
55
|
* actually provided (mirroring the server's all-optional content).
|
|
44
56
|
*/
|
|
45
|
-
|
|
57
|
+
function assembleContent(draft) {
|
|
46
58
|
const content = {};
|
|
47
59
|
const comment = draft.comment?.trim();
|
|
48
60
|
if (comment)
|
|
49
61
|
content.comment = comment;
|
|
50
|
-
const reporterName = draft.reporterName?.trim();
|
|
51
|
-
if (reporterName) {
|
|
52
|
-
content.reporterName = reporterName.slice(0, MAX_REPORTER_NAME_LENGTH);
|
|
53
|
-
}
|
|
54
|
-
const reporterEmail = draft.reporterEmail?.trim();
|
|
55
|
-
if (reporterEmail) {
|
|
56
|
-
content.reporterEmail = reporterEmail.slice(0, MAX_REPORTER_EMAIL_LENGTH);
|
|
57
|
-
}
|
|
58
62
|
if (draft.url)
|
|
59
63
|
content.url = draft.url;
|
|
60
64
|
if (draft.environment && Object.keys(draft.environment).length > 0) {
|
|
61
65
|
content.environment = draft.environment;
|
|
62
66
|
}
|
|
67
|
+
const deployEnvironment = draft.deployEnvironment?.trim();
|
|
68
|
+
if (deployEnvironment)
|
|
69
|
+
content.deployEnvironment = deployEnvironment;
|
|
63
70
|
// Only a non-empty trace rides along — an empty buffer is simply omitted.
|
|
64
71
|
if (draft.trace && draft.trace.length > 0)
|
|
65
72
|
content.trace = draft.trace;
|
|
66
73
|
return content;
|
|
67
74
|
}
|
|
75
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAgDH,gDA4BC;AAWD,0CAyBC;AA3ED;;;;;;;;;;GAUG;AACH,SAAgB,kBAAkB,CAChC,MAAyB,EACzB,UAAkB,EAClB,OAAgB;IAEhB,MAAM,GAAG,GAML,EAAE,CAAC;IAEP,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;IACjC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,GAAG,CAAC;QAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC;IACnC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;IAEzD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC;IAEvD,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC;IAEzD,OAAO,GAAG,CAAC;AACb,CAAC;AACD,wFAAwF;AACxF,qFAAqF;AACrF,kDAAkD;AAElD;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,KAAkB;IAChD,MAAM,OAAO,GAMT,EAAE,CAAC;IAEP,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACtC,IAAI,OAAO;QAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC;IAEvC,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IAEvC,IAAI,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnE,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;IAC1C,CAAC;IAED,MAAM,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAC1D,IAAI,iBAAiB;QAAE,OAAO,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IAErE,0EAA0E;IAC1E,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAEvE,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Expo **Reporter session** store (ADR-0032) — the storage binding only.
|
|
3
|
+
*
|
|
4
|
+
* After a Connect the SDK holds a compact signed token per origin and forwards it on
|
|
5
|
+
* every boot; the boot answer hands back a refreshed one (30-day sliding). On React
|
|
6
|
+
* Native the token is a real credential, so it lives in **Expo SecureStore**
|
|
7
|
+
* (Keychain / Keystore), not AsyncStorage — under a key **scoped by publishable key**
|
|
8
|
+
* (so two Projects in one app keep separate sessions), the key format shared with every
|
|
9
|
+
* SDK (`@fixback/sdk-core`). Persistence is best-effort: an unavailable or failing
|
|
10
|
+
* secure store simply means no stored session — the SDK falls back to anonymous rather
|
|
11
|
+
* than throwing, so it never disturbs the host app.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The SecureStore slice the SDK uses — `expo-secure-store`-shaped, injectable so the
|
|
15
|
+
* client is unit-tested without the native module. Absent ⇒ no persisted session.
|
|
16
|
+
*/
|
|
17
|
+
export interface SecureStorageLike {
|
|
18
|
+
getItemAsync(key: string): Promise<string | null>;
|
|
19
|
+
setItemAsync(key: string, value: string): Promise<void>;
|
|
20
|
+
deleteItemAsync(key: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** Read the stored Reporter session token for this Project, or `null`. Best-effort. */
|
|
23
|
+
export declare function readReporterSession(store: SecureStorageLike | null | undefined, publishableKey: string): Promise<string | null>;
|
|
24
|
+
/** Persist a Reporter session token for this Project. Best-effort. */
|
|
25
|
+
export declare function writeReporterSession(store: SecureStorageLike | null | undefined, publishableKey: string, token: string): Promise<void>;
|
|
26
|
+
/** Clear the stored Reporter session token for this Project (sign out). Best-effort. */
|
|
27
|
+
export declare function clearReporterSession(store: SecureStorageLike | null | undefined, publishableKey: string): Promise<void>;
|