@onekeyfe/react-native-tcp-socket 1.1.56

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.
@@ -0,0 +1,19 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "TcpSocket"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/OneKeyHQ/app-modules/react-native-tcp-socket.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm}"
17
+
18
+ install_modules_dependencies(s)
19
+ end
@@ -0,0 +1,77 @@
1
+ buildscript {
2
+ ext.getExtOrDefault = {name ->
3
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['RNTcpSocket_' + name]
4
+ }
5
+
6
+ repositories {
7
+ google()
8
+ mavenCentral()
9
+ }
10
+
11
+ dependencies {
12
+ classpath "com.android.tools.build:gradle:8.7.2"
13
+ // noinspection DifferentKotlinGradleVersion
14
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
15
+ }
16
+ }
17
+
18
+
19
+ apply plugin: "com.android.library"
20
+ apply plugin: "kotlin-android"
21
+
22
+ apply plugin: "com.facebook.react"
23
+
24
+ def getExtOrIntegerDefault(name) {
25
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["RNTcpSocket_" + name]).toInteger()
26
+ }
27
+
28
+ android {
29
+ namespace "com.rntcpsocket"
30
+
31
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
32
+
33
+ defaultConfig {
34
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
35
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
36
+ }
37
+
38
+ buildFeatures {
39
+ buildConfig true
40
+ }
41
+
42
+ buildTypes {
43
+ release {
44
+ minifyEnabled false
45
+ }
46
+ }
47
+
48
+ lintOptions {
49
+ disable "GradleCompatible"
50
+ }
51
+
52
+ compileOptions {
53
+ sourceCompatibility JavaVersion.VERSION_1_8
54
+ targetCompatibility JavaVersion.VERSION_1_8
55
+ }
56
+
57
+ sourceSets {
58
+ main {
59
+ java.srcDirs += [
60
+ "generated/java",
61
+ "generated/jni"
62
+ ]
63
+ }
64
+ }
65
+ }
66
+
67
+ repositories {
68
+ mavenCentral()
69
+ google()
70
+ }
71
+
72
+ def kotlin_version = getExtOrDefault("kotlinVersion")
73
+
74
+ dependencies {
75
+ implementation "com.facebook.react:react-android"
76
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
77
+ }
@@ -0,0 +1,35 @@
1
+ package com.rntcpsocket
2
+
3
+ import com.facebook.react.bridge.Promise
4
+ import com.facebook.react.bridge.ReactApplicationContext
5
+ import com.facebook.react.module.annotations.ReactModule
6
+ import java.net.InetSocketAddress
7
+ import java.net.Socket
8
+
9
+ @ReactModule(name = RNTcpSocketModule.NAME)
10
+ class RNTcpSocketModule(reactContext: ReactApplicationContext) :
11
+ NativeRNTcpSocketSpec(reactContext) {
12
+
13
+ companion object {
14
+ const val NAME = "RNTcpSocket"
15
+ }
16
+
17
+ override fun getName(): String = NAME
18
+
19
+ override fun connectWithTimeout(host: String, port: Double, timeoutMs: Double, promise: Promise) {
20
+ Thread {
21
+ try {
22
+ val portInt = port.toInt()
23
+ val timeout = timeoutMs.toInt()
24
+ val startTime = System.currentTimeMillis()
25
+ Socket().use { socket ->
26
+ socket.connect(InetSocketAddress(host, portInt), timeout)
27
+ }
28
+ val elapsed = System.currentTimeMillis() - startTime
29
+ promise.resolve(elapsed.toDouble())
30
+ } catch (e: Exception) {
31
+ promise.reject("TCP_SOCKET_ERROR", e.message, e)
32
+ }
33
+ }.start()
34
+ }
35
+ }
@@ -0,0 +1,33 @@
1
+ package com.rntcpsocket
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import java.util.HashMap
9
+
10
+ class RNTcpSocketPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == RNTcpSocketModule.NAME) {
13
+ RNTcpSocketModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
20
+ return ReactModuleInfoProvider {
21
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
22
+ moduleInfos[RNTcpSocketModule.NAME] = ReactModuleInfo(
23
+ RNTcpSocketModule.NAME,
24
+ RNTcpSocketModule.NAME,
25
+ false, // canOverrideExistingModule
26
+ false, // needsEagerInit
27
+ false, // isCxxModule
28
+ true // isTurboModule
29
+ )
30
+ moduleInfos
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,5 @@
1
+ #import <TcpSocketSpec/TcpSocketSpec.h>
2
+
3
+ @interface TcpSocket : NativeRNTcpSocketSpecBase <NativeRNTcpSocketSpec>
4
+
5
+ @end
@@ -0,0 +1,151 @@
1
+ #import "TcpSocket.h"
2
+
3
+ #include <arpa/inet.h>
4
+ #include <errno.h>
5
+ #include <fcntl.h>
6
+ #include <netdb.h>
7
+ #include <netinet/in.h>
8
+ #include <string.h>
9
+ #include <sys/select.h>
10
+ #include <sys/socket.h>
11
+ #include <sys/time.h>
12
+ #include <unistd.h>
13
+
14
+ @implementation TcpSocket
15
+
16
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
17
+ (const facebook::react::ObjCTurboModule::InitParams &)params
18
+ {
19
+ return std::make_shared<facebook::react::NativeRNTcpSocketSpecJSI>(params);
20
+ }
21
+
22
+ + (NSString *)moduleName
23
+ {
24
+ return @"RNTcpSocket";
25
+ }
26
+
27
+ + (BOOL)requiresMainQueueSetup
28
+ {
29
+ return NO;
30
+ }
31
+
32
+ // MARK: - connectWithTimeout
33
+
34
+ - (void)connectWithTimeout:(NSString *)host
35
+ port:(double)port
36
+ timeoutMs:(double)timeoutMs
37
+ resolve:(RCTPromiseResolveBlock)resolve
38
+ reject:(RCTPromiseRejectBlock)reject
39
+ {
40
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
41
+ NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970] * 1000.0;
42
+
43
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
44
+ if (sockfd < 0) {
45
+ reject(@"SOCKET_ERROR", @"Failed to create socket", nil);
46
+ return;
47
+ }
48
+
49
+ // Set non-blocking mode
50
+ int flags = fcntl(sockfd, F_GETFL, 0);
51
+ if (flags < 0) {
52
+ close(sockfd);
53
+ reject(@"SOCKET_ERROR", @"Failed to get socket flags", nil);
54
+ return;
55
+ }
56
+ if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) {
57
+ close(sockfd);
58
+ reject(@"SOCKET_ERROR", @"Failed to set non-blocking mode", nil);
59
+ return;
60
+ }
61
+
62
+ // Resolve hostname
63
+ struct addrinfo hints;
64
+ struct addrinfo *res = NULL;
65
+ memset(&hints, 0, sizeof(hints));
66
+ hints.ai_family = AF_UNSPEC;
67
+ hints.ai_socktype = SOCK_STREAM;
68
+
69
+ char portStr[16];
70
+ snprintf(portStr, sizeof(portStr), "%d", (int)port);
71
+
72
+ int gaiResult = getaddrinfo([host UTF8String], portStr, &hints, &res);
73
+ if (gaiResult != 0) {
74
+ close(sockfd);
75
+ reject(@"DNS_ERROR",
76
+ [NSString stringWithFormat:@"%s", gai_strerror(gaiResult)],
77
+ nil);
78
+ return;
79
+ }
80
+
81
+ // Attempt non-blocking connect
82
+ int connectResult = connect(sockfd, res->ai_addr, res->ai_addrlen);
83
+ freeaddrinfo(res);
84
+
85
+ if (connectResult < 0 && errno != EINPROGRESS) {
86
+ close(sockfd);
87
+ reject(@"CONNECT_ERROR",
88
+ [NSString stringWithUTF8String:strerror(errno)],
89
+ nil);
90
+ return;
91
+ }
92
+
93
+ // If already connected (unlikely for non-blocking, but handle it)
94
+ if (connectResult == 0) {
95
+ close(sockfd);
96
+ NSTimeInterval elapsed = [[NSDate date] timeIntervalSince1970] * 1000.0 - startTime;
97
+ resolve(@((NSInteger)elapsed));
98
+ return;
99
+ }
100
+
101
+ // Wait for connection with select() and timeout
102
+ fd_set writeSet;
103
+ FD_ZERO(&writeSet);
104
+ FD_SET(sockfd, &writeSet);
105
+
106
+ long timeoutLong = (long)timeoutMs;
107
+ struct timeval tv;
108
+ tv.tv_sec = timeoutLong / 1000;
109
+ tv.tv_usec = (int)((timeoutLong % 1000) * 1000);
110
+
111
+ int selectResult = select(sockfd + 1, NULL, &writeSet, NULL, &tv);
112
+
113
+ if (selectResult == 0) {
114
+ // Timeout
115
+ close(sockfd);
116
+ reject(@"ETIMEDOUT", @"Connection timeout", nil);
117
+ return;
118
+ }
119
+
120
+ if (selectResult < 0) {
121
+ close(sockfd);
122
+ reject(@"SELECT_ERROR",
123
+ [NSString stringWithUTF8String:strerror(errno)],
124
+ nil);
125
+ return;
126
+ }
127
+
128
+ // Check for socket-level error via getsockopt
129
+ int socketError = 0;
130
+ socklen_t optLen = sizeof(socketError);
131
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &socketError, &optLen) < 0) {
132
+ close(sockfd);
133
+ reject(@"CONNECT_ERROR", @"Failed to get socket error", nil);
134
+ return;
135
+ }
136
+
137
+ close(sockfd);
138
+
139
+ if (socketError != 0) {
140
+ reject(@"CONNECT_ERROR",
141
+ [NSString stringWithUTF8String:strerror(socketError)],
142
+ nil);
143
+ return;
144
+ }
145
+
146
+ NSTimeInterval elapsed = [[NSDate date] timeIntervalSince1970] * 1000.0 - startTime;
147
+ resolve(@((NSInteger)elapsed));
148
+ });
149
+ }
150
+
151
+ @end
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('RNTcpSocket');
5
+ //# sourceMappingURL=NativeTcpSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeTcpSocket.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,cAAc;AAgBlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,aAAa,CAAC","ignoreList":[]}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ import NativeTcpSocket from "./NativeTcpSocket.js";
4
+
5
+ // Compatibility shim that mimics the react-native-tcp-socket createConnection API
6
+ // but uses a simple Promise underneath (works in background Hermes runtime)
7
+
8
+ function createConnection(options, connectCallback) {
9
+ const timeout = options.timeout ?? 5000;
10
+ const handlers = {};
11
+ let destroyed = false;
12
+ NativeTcpSocket.connectWithTimeout(options.host, options.port, timeout).then(() => {
13
+ if (!destroyed) connectCallback();
14
+ }).catch(err => {
15
+ if (!destroyed) {
16
+ const errMsg = err instanceof Error ? err.message : String(err);
17
+ if (errMsg.includes('timeout') || errMsg.includes('ETIMEDOUT') || errMsg.includes('Connection timeout')) {
18
+ handlers.timeout?.();
19
+ } else if (handlers.error) {
20
+ handlers.error(err instanceof Error ? err : new Error(errMsg));
21
+ }
22
+ }
23
+ });
24
+ const shim = {
25
+ on(event, handler) {
26
+ if (event === 'error') {
27
+ handlers.error = handler;
28
+ } else if (event === 'timeout') {
29
+ handlers.timeout = handler;
30
+ }
31
+ return shim;
32
+ },
33
+ destroy() {
34
+ destroyed = true;
35
+ }
36
+ };
37
+ return shim;
38
+ }
39
+ export default {
40
+ createConnection
41
+ };
42
+ export { NativeTcpSocket };
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeTcpSocket","createConnection","options","connectCallback","timeout","handlers","destroyed","connectWithTimeout","host","port","then","catch","err","errMsg","Error","message","String","includes","error","shim","on","event","handler","destroy"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,eAAe,MAAM,sBAAmB;;AAE/C;AACA;;AAOA,SAASC,gBAAgBA,CACvBC,OAAyD,EACzDC,eAA2B,EACZ;EACf,MAAMC,OAAO,GAAGF,OAAO,CAACE,OAAO,IAAI,IAAI;EACvC,MAAMC,QAAgE,GAAG,CAAC,CAAC;EAE3E,IAAIC,SAAS,GAAG,KAAK;EAErBN,eAAe,CAACO,kBAAkB,CAACL,OAAO,CAACM,IAAI,EAAEN,OAAO,CAACO,IAAI,EAAEL,OAAO,CAAC,CACpEM,IAAI,CAAC,MAAM;IACV,IAAI,CAACJ,SAAS,EAAEH,eAAe,CAAC,CAAC;EACnC,CAAC,CAAC,CACDQ,KAAK,CAAEC,GAAY,IAAK;IACvB,IAAI,CAACN,SAAS,EAAE;MACd,MAAMO,MAAM,GACVD,GAAG,YAAYE,KAAK,GAAGF,GAAG,CAACG,OAAO,GAAGC,MAAM,CAACJ,GAAa,CAAC;MAC5D,IACEC,MAAM,CAACI,QAAQ,CAAC,SAAS,CAAC,IAC1BJ,MAAM,CAACI,QAAQ,CAAC,WAAW,CAAC,IAC5BJ,MAAM,CAACI,QAAQ,CAAC,oBAAoB,CAAC,EACrC;QACAZ,QAAQ,CAACD,OAAO,GAAG,CAAC;MACtB,CAAC,MAAM,IAAIC,QAAQ,CAACa,KAAK,EAAE;QACzBb,QAAQ,CAACa,KAAK,CAACN,GAAG,YAAYE,KAAK,GAAGF,GAAG,GAAG,IAAIE,KAAK,CAACD,MAAM,CAAC,CAAC;MAChE;IACF;EACF,CAAC,CAAC;EAEJ,MAAMM,IAAI,GAAG;IACXC,EAAEA,CAACC,KAAa,EAAEC,OAA8B,EAAE;MAChD,IAAID,KAAK,KAAK,OAAO,EAAE;QACrBhB,QAAQ,CAACa,KAAK,GAAGI,OAA+B;MAClD,CAAC,MAAM,IAAID,KAAK,KAAK,SAAS,EAAE;QAC9BhB,QAAQ,CAACD,OAAO,GAAGkB,OAAqB;MAC1C;MACA,OAAOH,IAAI;IACb,CAAC;IACDI,OAAOA,CAAA,EAAG;MACRjB,SAAS,GAAG,IAAI;IAClB;EACF,CAA6B;EAC7B,OAAOa,IAAI;AACb;AAEA,eAAe;EAAElB;AAAiB,CAAC;AACnC,SAASD,eAAe","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,11 @@
1
+ import type { TurboModule } from 'react-native';
2
+ export interface Spec extends TurboModule {
3
+ /**
4
+ * Attempt a TCP connection to host:port.
5
+ * Resolves with connection time in ms, rejects with error message.
6
+ */
7
+ connectWithTimeout(host: string, port: number, timeoutMs: number): Promise<number>;
8
+ }
9
+ declare const _default: Spec;
10
+ export default _default;
11
+ //# sourceMappingURL=NativeTcpSocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeTcpSocket.d.ts","sourceRoot":"","sources":["../../../src/NativeTcpSocket.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;;OAGG;IACH,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;;AAED,wBAAqE"}
@@ -0,0 +1,17 @@
1
+ import NativeTcpSocket from './NativeTcpSocket';
2
+ export interface TcpSocketShim {
3
+ on(event: 'error', handler: (err: Error) => void): this;
4
+ on(event: 'timeout', handler: () => void): this;
5
+ destroy(): void;
6
+ }
7
+ declare function createConnection(options: {
8
+ host: string;
9
+ port: number;
10
+ timeout?: number;
11
+ }, connectCallback: () => void): TcpSocketShim;
12
+ declare const _default: {
13
+ createConnection: typeof createConnection;
14
+ };
15
+ export default _default;
16
+ export { NativeTcpSocket };
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAIhD,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACxD,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAChD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,iBAAS,gBAAgB,CACvB,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,EACzD,eAAe,EAAE,MAAM,IAAI,GAC1B,aAAa,CAwCf;;;;AAED,wBAAoC;AACpC,OAAO,EAAE,eAAe,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,157 @@
1
+ {
2
+ "name": "@onekeyfe/react-native-tcp-socket",
3
+ "version": "1.1.56",
4
+ "description": "react-native-tcp-socket",
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
+ "ios",
19
+ "*.podspec",
20
+ "!ios/build",
21
+ "!**/__tests__",
22
+ "!**/__fixtures__",
23
+ "!**/__mocks__",
24
+ "!**/.*",
25
+ "android"
26
+ ],
27
+ "scripts": {
28
+ "clean": "del-cli ios/build lib",
29
+ "prepare": "bob build",
30
+ "typecheck": "tsc",
31
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
32
+ "test": "jest",
33
+ "release": "yarn prepare && npm whoami && npm publish --access public"
34
+ },
35
+ "keywords": [
36
+ "react-native",
37
+ "ios",
38
+ "tcp",
39
+ "socket"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/OneKeyHQ/app-modules/react-native-tcp-socket.git"
44
+ },
45
+ "author": "@onekeyhq <huanming@onekey.so> (https://github.com/OneKeyHQ/app-modules)",
46
+ "license": "MIT",
47
+ "bugs": {
48
+ "url": "https://github.com/OneKeyHQ/app-modules/react-native-tcp-socket/issues"
49
+ },
50
+ "homepage": "https://github.com/OneKeyHQ/app-modules/react-native-tcp-socket#readme",
51
+ "publishConfig": {
52
+ "registry": "https://registry.npmjs.org/"
53
+ },
54
+ "devDependencies": {
55
+ "@commitlint/config-conventional": "^19.8.1",
56
+ "@eslint/compat": "^1.3.2",
57
+ "@eslint/eslintrc": "^3.3.1",
58
+ "@eslint/js": "^9.35.0",
59
+ "@react-native/babel-preset": "0.83.0",
60
+ "@react-native/eslint-config": "0.83.0",
61
+ "@release-it/conventional-changelog": "^10.0.1",
62
+ "@types/jest": "^29.5.14",
63
+ "@types/react": "^19.2.0",
64
+ "commitlint": "^19.8.1",
65
+ "del-cli": "^6.0.0",
66
+ "eslint": "^9.35.0",
67
+ "eslint-config-prettier": "^10.1.8",
68
+ "eslint-plugin-prettier": "^5.5.4",
69
+ "jest": "^29.7.0",
70
+ "lefthook": "^2.0.3",
71
+ "prettier": "^2.8.8",
72
+ "react": "19.2.0",
73
+ "react-native": "patch:react-native@npm%3A0.83.0#~/.yarn/patches/react-native-npm-0.83.0-577d0f2d83.patch",
74
+ "react-native-builder-bob": "^0.40.17",
75
+ "release-it": "^19.0.4",
76
+ "turbo": "^2.5.6",
77
+ "typescript": "^5.9.2"
78
+ },
79
+ "peerDependencies": {
80
+ "react": "*",
81
+ "react-native": "*"
82
+ },
83
+ "react-native-builder-bob": {
84
+ "source": "src",
85
+ "output": "lib",
86
+ "targets": [
87
+ [
88
+ "module",
89
+ {
90
+ "esm": true
91
+ }
92
+ ],
93
+ [
94
+ "typescript",
95
+ {
96
+ "project": "tsconfig.build.json"
97
+ }
98
+ ]
99
+ ]
100
+ },
101
+ "codegenConfig": {
102
+ "name": "RNTcpSocketSpec",
103
+ "type": "modules",
104
+ "jsSrcsDir": "src",
105
+ "android": {
106
+ "javaPackageName": "com.rntcpsocket"
107
+ }
108
+ },
109
+ "prettier": {
110
+ "quoteProps": "consistent",
111
+ "singleQuote": true,
112
+ "tabWidth": 2,
113
+ "trailingComma": "es5",
114
+ "useTabs": false
115
+ },
116
+ "jest": {
117
+ "preset": "react-native",
118
+ "modulePathIgnorePatterns": [
119
+ "<rootDir>/lib/"
120
+ ]
121
+ },
122
+ "commitlint": {
123
+ "extends": [
124
+ "@commitlint/config-conventional"
125
+ ]
126
+ },
127
+ "release-it": {
128
+ "git": {
129
+ "commitMessage": "chore: release ${version}",
130
+ "tagName": "v${version}"
131
+ },
132
+ "npm": {
133
+ "publish": true
134
+ },
135
+ "github": {
136
+ "release": true
137
+ },
138
+ "plugins": {
139
+ "@release-it/conventional-changelog": {
140
+ "preset": {
141
+ "name": "angular"
142
+ }
143
+ }
144
+ }
145
+ },
146
+ "create-react-native-library": {
147
+ "type": "turbo-module",
148
+ "languages": "kotlin-objc",
149
+ "tools": [
150
+ "eslint",
151
+ "jest",
152
+ "lefthook",
153
+ "release-it"
154
+ ],
155
+ "version": "0.56.0"
156
+ }
157
+ }
@@ -0,0 +1,17 @@
1
+ import { TurboModuleRegistry } from 'react-native';
2
+
3
+ import type { TurboModule } from 'react-native';
4
+
5
+ export interface Spec extends TurboModule {
6
+ /**
7
+ * Attempt a TCP connection to host:port.
8
+ * Resolves with connection time in ms, rejects with error message.
9
+ */
10
+ connectWithTimeout(
11
+ host: string,
12
+ port: number,
13
+ timeoutMs: number,
14
+ ): Promise<number>;
15
+ }
16
+
17
+ export default TurboModuleRegistry.getEnforcing<Spec>('RNTcpSocket');
package/src/index.tsx ADDED
@@ -0,0 +1,57 @@
1
+ import NativeTcpSocket from './NativeTcpSocket';
2
+
3
+ // Compatibility shim that mimics the react-native-tcp-socket createConnection API
4
+ // but uses a simple Promise underneath (works in background Hermes runtime)
5
+ export interface TcpSocketShim {
6
+ on(event: 'error', handler: (err: Error) => void): this;
7
+ on(event: 'timeout', handler: () => void): this;
8
+ destroy(): void;
9
+ }
10
+
11
+ function createConnection(
12
+ options: { host: string; port: number; timeout?: number },
13
+ connectCallback: () => void,
14
+ ): TcpSocketShim {
15
+ const timeout = options.timeout ?? 5000;
16
+ const handlers: { error?: (err: Error) => void; timeout?: () => void } = {};
17
+
18
+ let destroyed = false;
19
+
20
+ NativeTcpSocket.connectWithTimeout(options.host, options.port, timeout)
21
+ .then(() => {
22
+ if (!destroyed) connectCallback();
23
+ })
24
+ .catch((err: unknown) => {
25
+ if (!destroyed) {
26
+ const errMsg =
27
+ err instanceof Error ? err.message : String(err as string);
28
+ if (
29
+ errMsg.includes('timeout') ||
30
+ errMsg.includes('ETIMEDOUT') ||
31
+ errMsg.includes('Connection timeout')
32
+ ) {
33
+ handlers.timeout?.();
34
+ } else if (handlers.error) {
35
+ handlers.error(err instanceof Error ? err : new Error(errMsg));
36
+ }
37
+ }
38
+ });
39
+
40
+ const shim = {
41
+ on(event: string, handler: (err?: Error) => void) {
42
+ if (event === 'error') {
43
+ handlers.error = handler as (err: Error) => void;
44
+ } else if (event === 'timeout') {
45
+ handlers.timeout = handler as () => void;
46
+ }
47
+ return shim as unknown as TcpSocketShim;
48
+ },
49
+ destroy() {
50
+ destroyed = true;
51
+ },
52
+ } as unknown as TcpSocketShim;
53
+ return shim;
54
+ }
55
+
56
+ export default { createConnection };
57
+ export { NativeTcpSocket };