react-native-newinstance-chat 0.1.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/package.json ADDED
@@ -0,0 +1,166 @@
1
+ {
2
+ "name": "react-native-newinstance-chat",
3
+ "version": "0.1.0",
4
+ "description": "New instance LiveAndAiChat React Native SDK — AI + live-agent chat, drop-in native chat screen for iOS and Android.",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-newinstance-chat-example",
36
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
37
+ "prepare": "bob build",
38
+ "typecheck": "tsc",
39
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
40
+ "test": "jest",
41
+ "release": "release-it --only-version",
42
+ "web": "vite",
43
+ "build:web": "vite build"
44
+ },
45
+ "keywords": [
46
+ "react-native",
47
+ "ios",
48
+ "android"
49
+ ],
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/talktothelaw/react-native-newinstance-chat.git"
53
+ },
54
+ "author": "lawrence <nwokolawrence6@gmail.com> (https://github.com/talktothelaw)",
55
+ "license": "MIT",
56
+ "bugs": {
57
+ "url": "https://github.com/talktothelaw/react-native-newinstance-chat/issues"
58
+ },
59
+ "homepage": "https://github.com/talktothelaw/react-native-newinstance-chat#readme",
60
+ "publishConfig": {
61
+ "registry": "https://registry.npmjs.org/"
62
+ },
63
+ "devDependencies": {
64
+ "@eslint/compat": "^2.0.3",
65
+ "@eslint/eslintrc": "^3.3.5",
66
+ "@eslint/js": "^10.0.1",
67
+ "@jest/globals": "^30.0.0",
68
+ "@react-native/babel-preset": "0.85.0",
69
+ "@react-native/eslint-config": "0.85.0",
70
+ "@react-native/jest-preset": "0.85.0",
71
+ "@release-it/conventional-changelog": "^10.0.6",
72
+ "@types/react": "^19.2.0",
73
+ "del-cli": "^7.0.0",
74
+ "eslint": "^9.39.4",
75
+ "eslint-config-prettier": "^10.1.8",
76
+ "eslint-plugin-ft-flow": "^3.0.11",
77
+ "eslint-plugin-prettier": "^5.5.5",
78
+ "jest": "^30.3.0",
79
+ "prettier": "^3.8.1",
80
+ "react": "19.2.3",
81
+ "react-native": "0.85.0",
82
+ "react-native-builder-bob": "^0.41.0",
83
+ "react-native-web": "~0.21.1",
84
+ "release-it": "^19.2.4",
85
+ "turbo": "^2.8.21",
86
+ "typescript": "^6.0.2"
87
+ },
88
+ "peerDependencies": {
89
+ "react": "*",
90
+ "react-native": "*"
91
+ },
92
+ "workspaces": [
93
+ "example"
94
+ ],
95
+ "packageManager": "yarn@4.11.0",
96
+ "react-native-builder-bob": {
97
+ "source": "src",
98
+ "output": "lib",
99
+ "targets": [
100
+ [
101
+ "module",
102
+ {
103
+ "esm": true
104
+ }
105
+ ],
106
+ [
107
+ "typescript",
108
+ {
109
+ "project": "tsconfig.build.json"
110
+ }
111
+ ]
112
+ ]
113
+ },
114
+ "codegenConfig": {
115
+ "name": "NewinstanceChatSpec",
116
+ "type": "modules",
117
+ "jsSrcsDir": "src",
118
+ "android": {
119
+ "javaPackageName": "com.newinstancechat"
120
+ }
121
+ },
122
+ "prettier": {
123
+ "quoteProps": "consistent",
124
+ "singleQuote": true,
125
+ "tabWidth": 2,
126
+ "trailingComma": "es5",
127
+ "useTabs": false
128
+ },
129
+ "jest": {
130
+ "preset": "@react-native/jest-preset",
131
+ "modulePathIgnorePatterns": [
132
+ "<rootDir>/example/node_modules",
133
+ "<rootDir>/lib/"
134
+ ]
135
+ },
136
+ "release-it": {
137
+ "git": {
138
+ "commitMessage": "chore: release ${version}",
139
+ "tagName": "v${version}"
140
+ },
141
+ "npm": {
142
+ "publish": true
143
+ },
144
+ "github": {
145
+ "release": true
146
+ },
147
+ "plugins": {
148
+ "@release-it/conventional-changelog": {
149
+ "preset": {
150
+ "name": "angular"
151
+ }
152
+ }
153
+ }
154
+ },
155
+ "create-react-native-library": {
156
+ "type": "turbo-module",
157
+ "languages": "kotlin-objc",
158
+ "tools": [
159
+ "eslint",
160
+ "jest",
161
+ "release-it",
162
+ "vite"
163
+ ],
164
+ "version": "0.62.0"
165
+ }
166
+ }
@@ -0,0 +1,30 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ /**
4
+ * TurboModule spec for the LiveAndAiChat React Native bridge. Codegen
5
+ * produces native protocol stubs from this file:
6
+ * - iOS: ios/build/.../NewinstanceChatSpec/NewinstanceChatSpec.h
7
+ * - Android: android/build/.../NativeNewinstanceChatSpec.java
8
+ *
9
+ * Dict-shaped arguments use `Object` because Codegen can't enforce
10
+ * deep object schemas; the JS class enforces the shapes via TypeScript
11
+ * before calling in.
12
+ */
13
+ export interface Spec extends TurboModule {
14
+ configure(config: Object): Promise<void>;
15
+ setUser(user: Object): void;
16
+ initialize(): Promise<void>;
17
+ openChat(): void;
18
+ closeChat(): void;
19
+ sendMessage(text: string): void;
20
+ retryMessage(messageId: string): void;
21
+ attachFile(opts: Object): Promise<void>;
22
+ destroy(): void;
23
+
24
+ // NativeEventEmitter on iOS calls these to track listener counts.
25
+ // Required even though native emit goes via RCTDeviceEventEmitter.
26
+ addListener(eventName: string): void;
27
+ removeListeners(count: number): void;
28
+ }
29
+
30
+ export default TurboModuleRegistry.getEnforcing<Spec>('NewinstanceChat');
package/src/index.tsx ADDED
@@ -0,0 +1,120 @@
1
+ import {
2
+ NativeEventEmitter,
3
+ NativeModules,
4
+ type EmitterSubscription,
5
+ } from 'react-native';
6
+
7
+ import NativeNewinstanceChat from './NativeNewinstanceChat';
8
+ import type {
9
+ AttachmentInput,
10
+ ChatUser,
11
+ EventHandler,
12
+ EventName,
13
+ NewinstanceChatConfig,
14
+ } from './types';
15
+
16
+ export type {
17
+ AttachmentInput,
18
+ ChatMessage,
19
+ ChatUser,
20
+ ConnectionState,
21
+ EventMap,
22
+ EventName,
23
+ NewinstanceChatConfig,
24
+ NewinstanceChatError,
25
+ NewinstanceChatErrorType,
26
+ } from './types';
27
+
28
+ // Bridge mode (old arch) exposes the module on NativeModules; new arch
29
+ // goes through TurboModuleRegistry. NativeEventEmitter accepts either —
30
+ // we feed it the legacy handle so listener counts get tracked.
31
+ const emitterSource: any =
32
+ NativeModules.NewinstanceChat ?? (NativeNewinstanceChat as unknown);
33
+ const emitter = new NativeEventEmitter(emitterSource);
34
+
35
+ /**
36
+ * React Native binding for the native LiveAndAiChat iOS / Android SDKs.
37
+ *
38
+ * Construct, optionally set a user, call `initialize()`, then `openChat()`
39
+ * when the host wants to surface the native chat screen. Subscribe to
40
+ * events with `addListener` — the returned function unsubscribes.
41
+ *
42
+ * Multiple `new NewinstanceChat(...)` calls reconfigure the same underlying
43
+ * native instance — the most recent `configure` wins.
44
+ */
45
+ export class NewinstanceChat {
46
+ /** Resolves once the native SDK is configured. */
47
+ readonly ready: Promise<void>;
48
+
49
+ constructor(config: NewinstanceChatConfig) {
50
+ this.ready = NativeNewinstanceChat.configure(config);
51
+ }
52
+
53
+ /**
54
+ * Identify the customer. Safe to call before or after `initialize()`. If
55
+ * called before `configure()` resolves, the user is queued and applied
56
+ * once the native instance exists.
57
+ */
58
+ setUser(user: ChatUser): void {
59
+ NativeNewinstanceChat.setUser(user);
60
+ }
61
+
62
+ /**
63
+ * Fetch org config, restore the saved conversation, and connect the
64
+ * subscription transport in the background. Concurrent callers share
65
+ * the same in-flight init.
66
+ */
67
+ initialize(): Promise<void> {
68
+ return NativeNewinstanceChat.initialize();
69
+ }
70
+
71
+ /** Present the native chat screen modally over the current RN host. */
72
+ openChat(): void {
73
+ NativeNewinstanceChat.openChat();
74
+ }
75
+
76
+ /** Dismiss the native chat screen. */
77
+ closeChat(): void {
78
+ NativeNewinstanceChat.closeChat();
79
+ }
80
+
81
+ sendMessage(text: string): void {
82
+ NativeNewinstanceChat.sendMessage(text);
83
+ }
84
+
85
+ retryMessage(messageId: string): void {
86
+ NativeNewinstanceChat.retryMessage(messageId);
87
+ }
88
+
89
+ /**
90
+ * Queue a local file as an attachment. The native side reads bytes from
91
+ * `uri`, pushes them through the SDK's upload pipeline, and bundles the
92
+ * uploaded reference into the next `sendMessage()`.
93
+ */
94
+ attachFile(opts: AttachmentInput): Promise<void> {
95
+ return NativeNewinstanceChat.attachFile(opts);
96
+ }
97
+
98
+ /**
99
+ * Subscribe to a native event. Returns an unsubscribe function — call it
100
+ * when your component unmounts to avoid leaks.
101
+ */
102
+ addListener<K extends EventName>(
103
+ event: K,
104
+ handler: EventHandler<K>
105
+ ): () => void {
106
+ const sub: EmitterSubscription = emitter.addListener(
107
+ event,
108
+ handler as (e: unknown) => void
109
+ );
110
+ return () => sub.remove();
111
+ }
112
+
113
+ /**
114
+ * Tear down the native SDK. After this the instance is unusable —
115
+ * construct a new one if you need to chat again.
116
+ */
117
+ destroy(): void {
118
+ NativeNewinstanceChat.destroy();
119
+ }
120
+ }
package/src/types.ts ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Public types for `react-native-newinstance-chat`.
3
+ *
4
+ * Shapes match what the native bridges produce, normalised across
5
+ * iOS / Android (e.g. message status / error type / connection state
6
+ * are lowercased string enums, not platform-specific enum values).
7
+ */
8
+
9
+ export interface NewinstanceChatConfig {
10
+ /** API key id from your newinstance.cloud dashboard. Never embed the secret half. */
11
+ apiKey: string;
12
+ /** Backend base URL. Defaults to `https://service.newinstance.cloud`. */
13
+ baseUrl?: string;
14
+ /** Subscription transport. `'sse'` (default in production), `'ws'`, or omit to let the server choose. */
15
+ transport?: 'sse' | 'ws';
16
+ /** Optional message pre-seeded as the first outbound message. */
17
+ initialMessage?: string;
18
+ }
19
+
20
+ export interface ChatUser {
21
+ customerName: string;
22
+ customerEmail?: string;
23
+ customerId?: string;
24
+ }
25
+
26
+ /** A local file the native side reads bytes from. */
27
+ export interface AttachmentInput {
28
+ /** Local file URI: `file://...` (iOS) or `content://...` / `file://...` (Android). */
29
+ uri: string;
30
+ name: string;
31
+ mimeType: string;
32
+ }
33
+
34
+ export type ConnectionState =
35
+ | 'idle'
36
+ | 'connecting'
37
+ | 'connected'
38
+ | 'disconnected'
39
+ | 'offline';
40
+
41
+ export interface ChatMessage {
42
+ id: string;
43
+ /** Client-side id used to dedupe a sent message against its server echo. */
44
+ clientId?: string;
45
+ conversationId: string;
46
+ content: string;
47
+ /** Lowercased enum from the native side: `'text'`, `'image'`, etc. */
48
+ type: string;
49
+ /** Lowercased enum: `'sent'`, `'delivered'`, `'failed'`, etc. */
50
+ status: string;
51
+ /** Server-assigned monotonic sequence number for ordering. */
52
+ seq?: number;
53
+ /** ISO-8601 timestamp string. */
54
+ sentAt?: string;
55
+ /**
56
+ * Total persisted messages in the conversation as of this envelope.
57
+ * Only present on `messageReceived`. The SDK uses this for silent
58
+ * gap-fill — if the locally-rendered count is below this, it refetches.
59
+ */
60
+ totalMessages?: number;
61
+ }
62
+
63
+ export type NewinstanceChatErrorType =
64
+ | 'network'
65
+ | 'validation'
66
+ | 'auth'
67
+ | 'system';
68
+
69
+ export interface NewinstanceChatError {
70
+ type: NewinstanceChatErrorType;
71
+ message: string;
72
+ recoverable: boolean;
73
+ }
74
+
75
+ /** Native event names. Subscribe with `sdk.addListener(event, handler)`. */
76
+ export interface EventMap {
77
+ messageReceived: (message: ChatMessage) => void;
78
+ messageSent: (message: ChatMessage) => void;
79
+ agentTypingChanged: (isTyping: boolean) => void;
80
+ connectionStateChanged: (state: ConnectionState) => void;
81
+ unreadCountChanged: (count: number) => void;
82
+ error: (e: NewinstanceChatError) => void;
83
+ }
84
+
85
+ export type EventName = keyof EventMap;
86
+ export type EventHandler<K extends EventName> = EventMap[K];