@getuserfeedback/react-native 5.0.7 → 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";
@@ -8,9 +8,9 @@ import { type NativeDirectCommandSession } from "./native-direct-command-session
8
8
  import type { NativeDirectCommandSessionController } from "./native-direct-command-session-controller.js";
9
9
  import { type NativeViewHostProjectionProps } from "./native-view-host-projection.js";
10
10
  export type NativeRuntimeRootProps = {
11
- coreUrl?: string;
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 {};
@@ -18,16 +18,8 @@ import { createNativeDirectCommandSession, } from "./native-direct-command-sessi
18
18
  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
- import { REACT_NATIVE_DEFAULT_CORE_URL } from "./runtime-endpoints.js";
22
21
  const DEFAULT_STARTUP_COMMAND_SETTLEMENT_TIMEOUT_MS = 30000;
23
- async function dispatchStartupCommands(input) {
24
- for (const command of input.commands) {
25
- await input.commandSession.dispatch(command, {
26
- settlementTimeoutMs: input.timeoutMs,
27
- });
28
- }
29
- }
30
- export function NativeRuntimeRoot({ coreUrl = REACT_NATIVE_DEFAULT_CORE_URL, 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, }) {
31
23
  const [coreHostRevision, setCoreHostRevision] = useState(0);
32
24
  const [session, setSession] = useState(null);
33
25
  const sessionRef = useRef(null);
@@ -43,8 +35,8 @@ export function NativeRuntimeRoot({ coreUrl = REACT_NATIVE_DEFAULT_CORE_URL, cor
43
35
  onInvalidMessageRef.current = onInvalidMessage;
44
36
  const onStartupTerminalErrorRef = useRef(onStartupTerminalError);
45
37
  onStartupTerminalErrorRef.current = onStartupTerminalError;
46
- const startupCommandsRef = useRef(startupCommands);
47
- startupCommandsRef.current = startupCommands;
38
+ const startupCommandRef = useRef(startupCommand);
39
+ startupCommandRef.current = startupCommand;
48
40
  const reportError = useCallback((error) => {
49
41
  var _a;
50
42
  try {
@@ -127,12 +119,11 @@ export function NativeRuntimeRoot({ coreUrl = REACT_NATIVE_DEFAULT_CORE_URL, cor
127
119
  setSession(nextSession);
128
120
  notifyCommandSessionObserver(nextSession.commandSessionObserver, commandSessionOwner.session);
129
121
  };
130
- const startupCommands = startupCommandsRef.current;
131
- if (startupCommands) {
132
- void dispatchStartupCommands({
133
- commands: startupCommands,
134
- commandSession: commandSessionOwner.session,
135
- timeoutMs: startupCommandSettlementTimeoutMs,
122
+ const startupCommand = startupCommandRef.current;
123
+ if (startupCommand) {
124
+ void commandSessionOwner.session
125
+ .dispatch(startupCommand, {
126
+ settlementTimeoutMs: startupCommandSettlementTimeoutMs,
136
127
  })
137
128
  .then(commitSession)
138
129
  .catch((error) => {
@@ -226,7 +217,7 @@ export function NativeRuntimeRoot({ coreUrl = REACT_NATIVE_DEFAULT_CORE_URL, cor
226
217
  }));
227
218
  }
228
219
  export function NativeProviderRuntime(_a) {
229
- 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"]);
230
221
  const directSessionRef = useRef(null);
231
222
  useLayoutEffect(() => {
232
223
  directSessionController.beginAttachmentAttempt();
@@ -255,22 +246,12 @@ export function NativeProviderRuntime(_a) {
255
246
  }
256
247
  onCommandSessionChange === null || onCommandSessionChange === void 0 ? void 0 : onCommandSessionChange(directSessionController.session);
257
248
  }, [directSessionController, onCommandSessionChange]);
258
- const startupCommands = useMemo(() => {
259
- const initCommand = createProviderCommandEnvelope({
249
+ const startupCommand = useMemo(() => {
250
+ return createProviderCommandEnvelope({
260
251
  clientMeta: REACT_NATIVE_CLIENT_META,
261
252
  command: { kind: "init", opts: initOptions },
262
253
  instanceId,
263
254
  });
264
- if (initialConfigureOptions === undefined) {
265
- return [initCommand];
266
- }
267
- return [
268
- initCommand,
269
- createProviderCommandEnvelope({
270
- command: { kind: "configure", opts: initialConfigureOptions },
271
- instanceId,
272
- }),
273
- ];
274
- }, [initialConfigureOptions, initOptions, instanceId]);
275
- 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 }));
276
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.7";
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.7",
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": {
@@ -1,2 +0,0 @@
1
- /** Core artifact pinned to this React Native package release. */
2
- export declare const REACT_NATIVE_DEFAULT_CORE_URL = "https://cdn.getuserfeedback.com/widget/core/v2/core.html";
@@ -1,2 +0,0 @@
1
- /** Core artifact pinned to this React Native package release. */
2
- export const REACT_NATIVE_DEFAULT_CORE_URL = "https://cdn.getuserfeedback.com/widget/core/v2/core.html";