@getuserfeedback/react-native 5.0.8 → 5.0.9

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.
@@ -1,22 +1,60 @@
1
- import { coreCommandEnvelopeSchema, } from "@getuserfeedback/protocol";
1
+ import { appEventPayloadSchema, coreCommandEnvelopeSchema, } from "@getuserfeedback/protocol";
2
2
  import { eventHandleInvalidatedSchema, } from "@getuserfeedback/protocol/internal/core-handle-invalidation";
3
3
  import { eventCommandSettledSchema, } from "@getuserfeedback/protocol/internal/core-host-command-settlement";
4
4
  import { CORE_SESSION_FAILED_CODE, eventCoreSessionFailedSchema, } from "@getuserfeedback/protocol/internal/core-session-failure";
5
+ import { buildRpcResponse, rpcRequestSchema, } from "@getuserfeedback/protocol/internal/v3-rpc-messages";
5
6
  const DISPOSED_MESSAGE = "Core command channel is disposed";
7
+ const TRAFFIC_APP_EVENT_RPC_METHOD = "traffic.appEvent";
6
8
  const isRecord = (value) => typeof value === "object" && value !== null;
7
9
  export function createNativeCoreCommandChannel(input) {
8
10
  const listeners = new Set();
9
11
  let disposed = false;
10
12
  const handleMessage = (value) => {
11
- var _a, _b, _c, _d, _e;
13
+ var _a, _b, _c, _d, _e, _f;
12
14
  if (disposed || !isRecord(value)) {
13
15
  return;
14
16
  }
17
+ if (value.t === "getuserfeedback:rpc:request") {
18
+ const parsed = rpcRequestSchema.safeParse(value);
19
+ if (!parsed.success ||
20
+ parsed.data.gen !== input.coreConnection.generation ||
21
+ parsed.data.method !== TRAFFIC_APP_EVENT_RPC_METHOD) {
22
+ return;
23
+ }
24
+ const params = isRecord(parsed.data.params) ? parsed.data.params : null;
25
+ const instanceId = params && typeof params.instanceId === "string"
26
+ ? params.instanceId.trim()
27
+ : "";
28
+ const payload = params
29
+ ? appEventPayloadSchema.safeParse(params.payload)
30
+ : { success: false };
31
+ const result = instanceId.length > 0 && payload.success
32
+ ? { allowed: true, payload: payload.data }
33
+ : { allowed: false };
34
+ try {
35
+ input.coreConnection.transport.postMessage(buildRpcResponse({
36
+ gen: parsed.data.gen,
37
+ rpcId: parsed.data.rpcId,
38
+ ok: true,
39
+ result,
40
+ viewId: parsed.data.viewId,
41
+ }));
42
+ }
43
+ catch (error) {
44
+ try {
45
+ (_a = input.onInvalidMessage) === null || _a === void 0 ? void 0 : _a.call(input, error instanceof Error ? error : new Error(String(error)), value);
46
+ }
47
+ catch (_g) {
48
+ // Best-effort analytics and diagnostics cannot fail the Core session.
49
+ }
50
+ }
51
+ return;
52
+ }
15
53
  if (value.t === "getuserfeedback:event:error" &&
16
54
  value.code === CORE_SESSION_FAILED_CODE) {
17
55
  const parsed = eventCoreSessionFailedSchema.safeParse(value);
18
56
  if (!parsed.success) {
19
- (_a = input.onInvalidMessage) === null || _a === void 0 ? void 0 : _a.call(input, parsed.error instanceof Error
57
+ (_b = input.onInvalidMessage) === null || _b === void 0 ? void 0 : _b.call(input, parsed.error instanceof Error
20
58
  ? parsed.error
21
59
  : new Error("Invalid Core session failure message"), value);
22
60
  return;
@@ -24,13 +62,13 @@ export function createNativeCoreCommandChannel(input) {
24
62
  if (parsed.data.gen !== input.coreConnection.generation) {
25
63
  return;
26
64
  }
27
- (_b = input.onSessionFailure) === null || _b === void 0 ? void 0 : _b.call(input, new Error(parsed.data.details.message));
65
+ (_c = input.onSessionFailure) === null || _c === void 0 ? void 0 : _c.call(input, new Error(parsed.data.details.message));
28
66
  return;
29
67
  }
30
68
  if (value.t === "getuserfeedback:event:commandSettled") {
31
69
  const parsed = eventCommandSettledSchema.safeParse(value);
32
70
  if (!parsed.success) {
33
- (_c = input.onInvalidMessage) === null || _c === void 0 ? void 0 : _c.call(input, parsed.error instanceof Error
71
+ (_d = input.onInvalidMessage) === null || _d === void 0 ? void 0 : _d.call(input, parsed.error instanceof Error
34
72
  ? parsed.error
35
73
  : new Error("Invalid core command settlement message"), value);
36
74
  return;
@@ -48,7 +86,7 @@ export function createNativeCoreCommandChannel(input) {
48
86
  }
49
87
  const parsed = eventHandleInvalidatedSchema.safeParse(value);
50
88
  if (!parsed.success) {
51
- (_d = input.onInvalidMessage) === null || _d === void 0 ? void 0 : _d.call(input, parsed.error instanceof Error
89
+ (_e = input.onInvalidMessage) === null || _e === void 0 ? void 0 : _e.call(input, parsed.error instanceof Error
52
90
  ? parsed.error
53
91
  : new Error("Invalid core handle invalidation message"), value);
54
92
  return;
@@ -56,7 +94,7 @@ export function createNativeCoreCommandChannel(input) {
56
94
  if (parsed.data.gen !== input.coreConnection.generation) {
57
95
  return;
58
96
  }
59
- (_e = input.onHandleInvalidated) === null || _e === void 0 ? void 0 : _e.call(input, parsed.data);
97
+ (_f = input.onHandleInvalidated) === null || _f === void 0 ? void 0 : _f.call(input, parsed.data);
60
98
  };
61
99
  const unsubscribeTransport = input.coreConnection.transport.subscribe(handleMessage);
62
100
  const channel = {
@@ -3,7 +3,7 @@ export declare function createNativeProviderClientController(input: {
3
3
  instanceId: string;
4
4
  onError?: (error: Error) => void;
5
5
  }): {
6
- client: import("./native-provider-client.js").NativeProviderClient<void>;
6
+ client: import("./client.js").Client;
7
7
  directSessionController: import("./native-direct-command-session-controller.js").NativeDirectCommandSessionController;
8
8
  dispose: () => void;
9
9
  onHandleInvalidated: (message: EventHandleInvalidated) => void;
@@ -1,43 +1,14 @@
1
- import type { AppEventExternalId, AppEventJsonValue, PublicCommandPayload } from "@getuserfeedback/protocol";
2
- import type { ConfigureOptions } from "@getuserfeedback/sdk";
3
- import type { FlowRun } from "./client.js";
4
- type IdentifyTraits = Record<string, unknown>;
5
- type TrackProperties = Record<string, AppEventJsonValue>;
1
+ import type { PublicCommandPayload } from "@getuserfeedback/protocol";
2
+ import type { Client } from "./client.js";
6
3
  type NativeProviderClientCommand = Extract<PublicCommandPayload, {
7
4
  kind: "configure" | "identify" | "track" | "close" | "reset" | "updateHostContext" | "emitHostSignal";
8
5
  }>;
9
- type IdentifyOptions = {
10
- externalIds?: AppEventExternalId[];
11
- };
12
- type TrackOptions = {
13
- externalIds?: AppEventExternalId[];
14
- };
15
- type HostContext = Extract<PublicCommandPayload, {
16
- kind: "updateHostContext";
17
- }>["context"];
18
- interface NativeProviderCommandOptions {
19
- idempotencyKey?: string;
20
- }
21
- export interface NativeProviderClient<TResult> {
22
- readonly instanceId: string;
23
- configure: (opts: ConfigureOptions, options?: NativeProviderCommandOptions) => Promise<TResult>;
24
- identify: {
25
- (userId: string, traits?: IdentifyTraits, options?: IdentifyOptions): Promise<TResult>;
26
- (traits: IdentifyTraits, placeholder: undefined, options?: IdentifyOptions): Promise<TResult>;
27
- (traits: IdentifyTraits, options?: IdentifyOptions): Promise<TResult>;
28
- };
29
- track: (eventName: string, properties?: TrackProperties, options?: TrackOptions) => Promise<TResult>;
30
- flow: (flowId: string) => FlowRun;
31
- close: () => Promise<TResult>;
32
- reset: (options?: NativeProviderCommandOptions) => Promise<TResult>;
33
- updateHostContext: (context: HostContext, options?: NativeProviderCommandOptions) => Promise<TResult>;
34
- emitHostSignal: (name: string, data?: unknown, options?: NativeProviderCommandOptions) => Promise<TResult>;
35
- }
36
- type NativeProviderClientOptions<TResult> = {
37
- dispatchCommand: (command: NativeProviderClientCommand, options?: NativeProviderCommandOptions) => Promise<TResult>;
38
- flow: (flowId: string) => FlowRun;
6
+ type NativeProviderCommandOptions = NonNullable<Parameters<Client["configure"]>[1]>;
7
+ type NativeProviderClientOptions = {
8
+ dispatchCommand: (command: NativeProviderClientCommand, options?: NativeProviderCommandOptions) => Promise<void>;
9
+ flow: Client["flow"];
39
10
  instanceId: string;
40
11
  };
41
12
  export declare const parseRequiredString: (name: string, value?: string) => string;
42
- export declare function createNativeProviderClient<TResult>({ dispatchCommand, flow, instanceId, }: NativeProviderClientOptions<TResult>): NativeProviderClient<TResult>;
13
+ export declare function createNativeProviderClient({ dispatchCommand, flow, instanceId, }: NativeProviderClientOptions): Client;
43
14
  export {};
@@ -1,6 +1,6 @@
1
1
  import type { CoreCommandEnvelope } from "@getuserfeedback/protocol";
2
2
  import type { EventHandleInvalidated } from "@getuserfeedback/protocol/internal/core-handle-invalidation";
3
- import type { ConfigureOptions, InitOptions } from "@getuserfeedback/sdk";
3
+ import type { InitOptions } from "@getuserfeedback/sdk";
4
4
  import { type ReactElement } from "react";
5
5
  import { type CoreWebViewHostProps } from "./core-webview-host.js";
6
6
  import { type NativeCoreCommandSession } from "./native-core-command-session.js";
@@ -10,7 +10,7 @@ import { type NativeViewHostProjectionProps } from "./native-view-host-projectio
10
10
  export type NativeRuntimeRootProps = {
11
11
  coreUrl: string;
12
12
  coreWebViewComponent?: CoreWebViewHostProps["webViewComponent"];
13
- startupCommands?: NativeRuntimeStartupCommands;
13
+ startupCommand?: NativeRuntimeInitCommand;
14
14
  onCommandSessionChange?: (session: NativeCoreCommandSession | null) => void;
15
15
  onError?: (error: Error) => void;
16
16
  onHandleInvalidated?: (message: EventHandleInvalidated) => void;
@@ -25,20 +25,13 @@ type NativeRuntimeInitCommand = Omit<CoreCommandEnvelope, "command"> & {
25
25
  kind: "init";
26
26
  }>;
27
27
  };
28
- type NativeRuntimeConfigureCommand = Omit<CoreCommandEnvelope, "command"> & {
29
- command: Extract<CoreCommandEnvelope["command"], {
30
- kind: "configure";
31
- }>;
32
- };
33
- type NativeRuntimeStartupCommands = readonly [NativeRuntimeInitCommand] | readonly [NativeRuntimeInitCommand, NativeRuntimeConfigureCommand];
34
- type NativeProviderRuntimeProps = Omit<NativeRuntimeRootProps, "onCommandSessionChange" | "onStartupTerminalError" | "startupCommands"> & {
28
+ type NativeProviderRuntimeProps = Omit<NativeRuntimeRootProps, "onCommandSessionChange" | "onStartupTerminalError" | "startupCommand"> & {
35
29
  /** Stable, exclusive controller retained and disposed by the component that owns this runtime's mounted lifetime. */
36
30
  directSessionController: NativeDirectCommandSessionController;
37
- initialConfigureOptions?: ConfigureOptions;
38
31
  initOptions: InitOptions;
39
32
  instanceId: string;
40
33
  onCommandSessionChange?: (session: NativeDirectCommandSession | null) => void;
41
34
  };
42
- export declare function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSessionChange, onError, onHandleInvalidated, onInvalidMessage, onStartupTerminalError, startupCommandSettlementTimeoutMs, startupCommands, viewNativeViewComponent, viewWebViewComponent, }: NativeRuntimeRootProps): ReactElement;
43
- export declare function NativeProviderRuntime({ directSessionController, initOptions, initialConfigureOptions, instanceId, onCommandSessionChange, onError, ...runtimeProps }: NativeProviderRuntimeProps): ReactElement;
35
+ export declare function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSessionChange, onError, onHandleInvalidated, onInvalidMessage, onStartupTerminalError, startupCommandSettlementTimeoutMs, startupCommand, viewNativeViewComponent, viewWebViewComponent, }: NativeRuntimeRootProps): ReactElement;
36
+ export declare function NativeProviderRuntime({ directSessionController, initOptions, instanceId, onCommandSessionChange, onError, ...runtimeProps }: NativeProviderRuntimeProps): ReactElement;
44
37
  export {};
@@ -19,14 +19,7 @@ import { NativeViewHostProjection, } from "./native-view-host-projection.js";
19
19
  import { createNativeViewRecordController, } from "./native-view-record-controller.js";
20
20
  import { createProviderCommandEnvelope, REACT_NATIVE_CLIENT_META, } from "./provider-command-helpers.js";
21
21
  const DEFAULT_STARTUP_COMMAND_SETTLEMENT_TIMEOUT_MS = 30000;
22
- async function dispatchStartupCommands(input) {
23
- for (const command of input.commands) {
24
- await input.commandSession.dispatch(command, {
25
- settlementTimeoutMs: input.timeoutMs,
26
- });
27
- }
28
- }
29
- export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSessionChange, onError, onHandleInvalidated, onInvalidMessage, onStartupTerminalError, startupCommandSettlementTimeoutMs = DEFAULT_STARTUP_COMMAND_SETTLEMENT_TIMEOUT_MS, startupCommands, viewNativeViewComponent, viewWebViewComponent, }) {
22
+ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSessionChange, onError, onHandleInvalidated, onInvalidMessage, onStartupTerminalError, startupCommandSettlementTimeoutMs = DEFAULT_STARTUP_COMMAND_SETTLEMENT_TIMEOUT_MS, startupCommand, viewNativeViewComponent, viewWebViewComponent, }) {
30
23
  const [coreHostRevision, setCoreHostRevision] = useState(0);
31
24
  const [session, setSession] = useState(null);
32
25
  const sessionRef = useRef(null);
@@ -42,8 +35,8 @@ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSess
42
35
  onInvalidMessageRef.current = onInvalidMessage;
43
36
  const onStartupTerminalErrorRef = useRef(onStartupTerminalError);
44
37
  onStartupTerminalErrorRef.current = onStartupTerminalError;
45
- const startupCommandsRef = useRef(startupCommands);
46
- startupCommandsRef.current = startupCommands;
38
+ const startupCommandRef = useRef(startupCommand);
39
+ startupCommandRef.current = startupCommand;
47
40
  const reportError = useCallback((error) => {
48
41
  var _a;
49
42
  try {
@@ -126,12 +119,11 @@ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSess
126
119
  setSession(nextSession);
127
120
  notifyCommandSessionObserver(nextSession.commandSessionObserver, commandSessionOwner.session);
128
121
  };
129
- const startupCommands = startupCommandsRef.current;
130
- if (startupCommands) {
131
- void dispatchStartupCommands({
132
- commands: startupCommands,
133
- commandSession: commandSessionOwner.session,
134
- timeoutMs: startupCommandSettlementTimeoutMs,
122
+ const startupCommand = startupCommandRef.current;
123
+ if (startupCommand) {
124
+ void commandSessionOwner.session
125
+ .dispatch(startupCommand, {
126
+ settlementTimeoutMs: startupCommandSettlementTimeoutMs,
135
127
  })
136
128
  .then(commitSession)
137
129
  .catch((error) => {
@@ -225,7 +217,7 @@ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, onCommandSess
225
217
  }));
226
218
  }
227
219
  export function NativeProviderRuntime(_a) {
228
- var { directSessionController, initOptions, initialConfigureOptions, instanceId, onCommandSessionChange, onError } = _a, runtimeProps = __rest(_a, ["directSessionController", "initOptions", "initialConfigureOptions", "instanceId", "onCommandSessionChange", "onError"]);
220
+ var { directSessionController, initOptions, instanceId, onCommandSessionChange, onError } = _a, runtimeProps = __rest(_a, ["directSessionController", "initOptions", "instanceId", "onCommandSessionChange", "onError"]);
229
221
  const directSessionRef = useRef(null);
230
222
  useLayoutEffect(() => {
231
223
  directSessionController.beginAttachmentAttempt();
@@ -254,22 +246,12 @@ export function NativeProviderRuntime(_a) {
254
246
  }
255
247
  onCommandSessionChange === null || onCommandSessionChange === void 0 ? void 0 : onCommandSessionChange(directSessionController.session);
256
248
  }, [directSessionController, onCommandSessionChange]);
257
- const startupCommands = useMemo(() => {
258
- const initCommand = createProviderCommandEnvelope({
249
+ const startupCommand = useMemo(() => {
250
+ return createProviderCommandEnvelope({
259
251
  clientMeta: REACT_NATIVE_CLIENT_META,
260
252
  command: { kind: "init", opts: initOptions },
261
253
  instanceId,
262
254
  });
263
- if (initialConfigureOptions === undefined) {
264
- return [initCommand];
265
- }
266
- return [
267
- initCommand,
268
- createProviderCommandEnvelope({
269
- command: { kind: "configure", opts: initialConfigureOptions },
270
- instanceId,
271
- }),
272
- ];
273
- }, [initialConfigureOptions, initOptions, instanceId]);
274
- return createElement(NativeRuntimeRoot, Object.assign(Object.assign({}, runtimeProps), { onCommandSessionChange: handleCommandSessionChange, onError, onStartupTerminalError: handleStartupTerminalError, startupCommands }));
255
+ }, [initOptions, instanceId]);
256
+ return createElement(NativeRuntimeRoot, Object.assign(Object.assign({}, runtimeProps), { onCommandSessionChange: handleCommandSessionChange, onError, onStartupTerminalError: handleStartupTerminalError, startupCommand }));
275
257
  }
package/dist/version.js CHANGED
@@ -3,4 +3,4 @@ const reactNativeSdkVersion = typeof __GX_REACT_NATIVE_SDK_VERSION__ === "string
3
3
  : "";
4
4
  // Build scripts patch this fallback to the package version for published artifacts.
5
5
  // Source-linked workspace usage keeps the local fallback.
6
- export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "5.0.8";
6
+ export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "5.0.9";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getuserfeedback/react-native",
3
- "version": "5.0.8",
3
+ "version": "5.0.9",
4
4
  "description": "getuserfeedback React Native SDK",
5
5
  "keywords": [
6
6
  "getuserfeedback",
@@ -38,14 +38,14 @@
38
38
  "publish:dry-run": "node ../../scripts/publish-package.cjs . --verify-packed-runtime scripts/verify-packed-runtime.ts --expect-dependency @getuserfeedback/protocol:../protocol/package.json --expect-dependency @getuserfeedback/sdk:../sdk/package.json -- --dry-run",
39
39
  "publish:npm": "node ../../scripts/publish-package.cjs . --verify-packed-runtime scripts/verify-packed-runtime.ts --expect-dependency @getuserfeedback/protocol:../protocol/package.json --expect-dependency @getuserfeedback/sdk:../sdk/package.json",
40
40
  "build": "bun scripts/build.ts",
41
- "typecheck": "tsc -p tsconfig.json --noEmit --tsBuildInfoFile tsconfig.typecheck.tsbuildinfo && tsc -p tsconfig-scripts.json",
41
+ "typecheck": "tsc -p tsconfig.json --noEmit --composite false --incremental false && tsc -p tsconfig-scripts.json --noEmit --composite false --incremental false",
42
42
  "test": "bun test --dots",
43
43
  "test:changed": "bun test --changed=${TEST_CHANGED_BASE:-HEAD} --pass-with-no-tests --dots",
44
44
  "lint": "biome check ."
45
45
  },
46
46
  "dependencies": {
47
- "@getuserfeedback/protocol": "^3.31.0",
48
- "@getuserfeedback/sdk": "^0.12.35",
47
+ "@getuserfeedback/protocol": "^3.31.1",
48
+ "@getuserfeedback/sdk": "^0.12.36",
49
49
  "robot3": "^1.2.0"
50
50
  },
51
51
  "peerDependencies": {