@fixback/expo 0.1.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.
Files changed (58) hide show
  1. package/README.md +72 -8
  2. package/dist/FeedbackModal.d.ts +10 -2
  3. package/dist/FeedbackModal.js +84 -36
  4. package/dist/FeedbackModal.js.map +1 -0
  5. package/dist/FixbackProvider.d.ts +12 -0
  6. package/dist/FixbackProvider.js +46 -23
  7. package/dist/FixbackProvider.js.map +1 -0
  8. package/dist/adapters.js +73 -23
  9. package/dist/adapters.js.map +1 -0
  10. package/dist/breadcrumbs.d.ts +21 -222
  11. package/dist/breadcrumbs.js +45 -605
  12. package/dist/breadcrumbs.js.map +1 -0
  13. package/dist/client.d.ts +65 -67
  14. package/dist/client.js +288 -151
  15. package/dist/client.js.map +1 -0
  16. package/dist/connect.d.ts +60 -0
  17. package/dist/connect.js +63 -0
  18. package/dist/connect.js.map +1 -0
  19. package/dist/error-capture.d.ts +29 -79
  20. package/dist/error-capture.js +77 -295
  21. package/dist/error-capture.js.map +1 -0
  22. package/dist/http.d.ts +10 -25
  23. package/dist/http.js +15 -12
  24. package/dist/http.js.map +1 -0
  25. package/dist/identity.d.ts +11 -11
  26. package/dist/identity.js +23 -28
  27. package/dist/identity.js.map +1 -0
  28. package/dist/index.d.ts +6 -5
  29. package/dist/index.js +22 -5
  30. package/dist/index.js.map +1 -0
  31. package/dist/origin.d.ts +21 -0
  32. package/dist/origin.js +45 -0
  33. package/dist/origin.js.map +1 -0
  34. package/dist/package.json +3 -0
  35. package/dist/report.d.ts +28 -63
  36. package/dist/report.js +33 -25
  37. package/dist/report.js.map +1 -0
  38. package/dist/reporter-session-store.d.ts +27 -0
  39. package/dist/reporter-session-store.js +53 -0
  40. package/dist/reporter-session-store.js.map +1 -0
  41. package/dist/shake.d.ts +26 -0
  42. package/dist/shake.js +32 -7
  43. package/dist/shake.js.map +1 -0
  44. package/dist/submit.d.ts +24 -15
  45. package/dist/submit.js +30 -47
  46. package/dist/submit.js.map +1 -0
  47. package/dist/tokens.js +5 -1
  48. package/dist/tokens.js.map +1 -0
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +5 -1
  51. package/dist/version.js.map +1 -0
  52. package/package.json +14 -7
  53. package/dist/auto-report-backoff.d.ts +0 -42
  54. package/dist/auto-report-backoff.js +0 -67
  55. package/dist/boot.d.ts +0 -65
  56. package/dist/boot.js +0 -60
  57. package/dist/scrub.d.ts +0 -55
  58. package/dist/scrub.js +0 -184
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-capture.js","sourceRoot":"","sources":["../src/error-capture.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -1,31 +1,16 @@
1
1
  /**
2
- * Minimal structural types for the HTTP surface the SDK touches.
2
+ * The **`FormData` slice** the multipart submission uses — the one HTTP shape that
3
+ * is genuinely React Native's own.
3
4
  *
4
- * The package typechecks without the DOM lib (React Native is not a browser), so
5
- * rather than depending on ambient `fetch`/`FormData` declarations, the exact
6
- * slices the transport uses are described here and the globals are read off
7
- * `globalThis` defensively. React Native provides both at runtime; tests inject
8
- * fakes through the same seams.
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
- * Minimal structural types for the HTTP surface the SDK touches.
3
+ * The **`FormData` slice** the multipart submission uses — the one HTTP shape that
4
+ * is genuinely React Native's own.
3
5
  *
4
- * The package typechecks without the DOM lib (React Native is not a browser), so
5
- * rather than depending on ambient `fetch`/`FormData` declarations, the exact
6
- * slices the transport uses are described here and the globals are read off
7
- * `globalThis` defensively. React Native provides both at runtime; tests inject
8
- * fakes through the same seams.
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
- /** React Native's global `fetch`, when present. Bound so `this` never matters. */
11
- export function globalFetch() {
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
- export function globalFormData() {
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
@@ -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"}
@@ -1,22 +1,22 @@
1
1
  /**
2
- * The Public Reporter's stable, first-party anonymous id — the mobile
3
- * counterpart of `packages/sdk/src/identity.ts`.
2
+ * The Public Reporter's anonymous id on React Native — the **storage binding**
3
+ * only.
4
4
  *
5
- * When the host app does not supply its own identity, the SDK establishes a
6
- * per-device id and persists it (AsyncStorage on React Native), so repeated
7
- * boots from the same device are one Reporter. Persistence is best-effort: if
8
- * storage is unavailable or failing, we fall back to an ephemeral id rather
9
- * than throw — the SDK must never disturb the host app. The storage key is the
10
- * web SDK's, so the shape stays recognisable across clients.
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 stable, first-party anonymous id — the mobile
3
- * counterpart of `packages/sdk/src/identity.ts`.
3
+ * The Public Reporter's anonymous id on React Native — the **storage binding**
4
+ * only.
4
5
  *
5
- * When the host app does not supply its own identity, the SDK establishes a
6
- * per-device id and persists it (AsyncStorage on React Native), so repeated
7
- * boots from the same device are one Reporter. Persistence is best-effort: if
8
- * storage is unavailable or failing, we fall back to an ephemeral id rather
9
- * than throw — the SDK must never disturb the host app. The storage key is the
10
- * web SDK's, so the shape stays recognisable across clients.
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
- export const ANONYMOUS_ID_STORAGE_KEY = "fixback.anonymousId";
13
- /** A random id: a UUID where the platform offers one, else a compact fallback. */
14
- export function generateAnonymousId() {
15
- const c = globalThis.crypto;
16
- if (c && typeof c.randomUUID === "function") {
17
- try {
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
- export async function ensureAnonymousId(storage) {
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 "./boot";
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
- export { Fixback, FixbackProvider, useFixback, } from "./FixbackProvider";
8
- export { canonicalizeOrigin, createFixbackClient, DEFAULT_API_URL, DEFAULT_SHAKE_SAMPLE_INTERVAL_MS, } from "./client";
9
- export { createShakeDetector, DEFAULT_SHAKE_TUNING, } from "./shake";
10
- export { EXPO_SDK_VERSION } from "./version";
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"}
@@ -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"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
package/dist/report.d.ts CHANGED
@@ -1,63 +1,33 @@
1
1
  /**
2
- * The ingest **feedback** content wire-contract, vendored, plus the helpers
3
- * that assemble it from what a Reporter composed — kept file-parallel with
4
- * `packages/sdk/src/report.ts` (ADR-0021). The mobile slice carries no
5
- * `annotation` (element picking and drawing are web-only today, spec 0004 §G);
6
- * every content field is optional on the server, so the payload simply omits it.
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 "./breadcrumbs";
9
- /**
10
- * Where a Feedback came from — a human in the composer (`reporter`, the
11
- * default) or the SDK's automatic error capture (`auto`). Mirrors the server's
12
- * `FEEDBACK_SOURCES`; the server derives trust independently.
13
- */
14
- export type FeedbackSource = "reporter" | "auto";
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 `auto` by the SDK's error capture.
45
- */
46
- readonly source?: FeedbackSource;
47
- /** For `source: auto` only — the SDK's per-session error fingerprint. */
48
- readonly errorSignature?: string;
49
- /** For `source: auto` 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
- /** The Reporter's self-provided display name / email, if the SDK holds them. */
59
- readonly reporterName?: string;
60
- readonly reporterEmail?: string;
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
- * The ingest **feedback** content wire-contract, vendored, plus the helpers
3
- * that assemble it from what a Reporter composed — kept file-parallel with
4
- * `packages/sdk/src/report.ts` (ADR-0021). The mobile slice carries no
5
- * `annotation` (element picking and drawing are web-only today, spec 0004 §G);
6
- * every content field is optional on the server, so the payload simply omits it.
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
- export function collectEnvironment(inputs, sdkVersion) {
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
- * The server's hard bounds on the display-only reporter fields
31
- * (`feedbackContentBody` in `apps/api/src/ingest/ingest.controller.ts`). An
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
- export function assembleContent(draft) {
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>;