@rn-bridge-tools/core 1.0.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/dist/index.cjs ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ createMessageId: () => createMessageId,
24
+ deserialize: () => deserialize,
25
+ moduleNotInstalledError: () => moduleNotInstalledError,
26
+ serialize: () => serialize,
27
+ tryImport: () => tryImport
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/utils.ts
32
+ var messageCounter = 0;
33
+ function createMessageId() {
34
+ messageCounter += 1;
35
+ return `bt_${Date.now()}_${messageCounter}`;
36
+ }
37
+ function serialize(data) {
38
+ return JSON.stringify(data);
39
+ }
40
+ function deserialize(data) {
41
+ return JSON.parse(data);
42
+ }
43
+ function tryImport(moduleName) {
44
+ try {
45
+ return require(moduleName);
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
50
+ function moduleNotInstalledError(moduleName) {
51
+ return {
52
+ success: false,
53
+ error: `MODULE_NOT_INSTALLED: ${moduleName}`
54
+ };
55
+ }
56
+ // Annotate the CommonJS export names for ESM import in node:
57
+ 0 && (module.exports = {
58
+ createMessageId,
59
+ deserialize,
60
+ moduleNotInstalledError,
61
+ serialize,
62
+ tryImport
63
+ });
64
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/utils.ts"],"sourcesContent":["// Types\nexport type {\n BridgeAction,\n BridgeNamespace,\n BridgeSchema,\n BridgeRequest,\n BridgeResponse,\n BridgeEventMap,\n BridgeMessage,\n BridgeResponseMessage,\n BridgeEventMessage,\n BridgeHandler,\n BridgeHandlerMap,\n HandlerOptions,\n NamespaceKey,\n} from './types.js';\n\n// Schema\nexport type {\n BridgeToolsSchema,\n BridgeToolsAction,\n BridgeToolsEvents,\n BridgeToolsEvent,\n} from './schema.js';\n\n// Namespace types\nexport type { CameraNamespace } from './namespaces/camera.js';\nexport type { LocationNamespace, LocationEvents } from './namespaces/location.js';\nexport type { FileNamespace } from './namespaces/file.js';\nexport type { ShareNamespace } from './namespaces/share.js';\nexport type { DeviceNamespace } from './namespaces/device.js';\nexport type { StatusBarNamespace } from './namespaces/statusbar.js';\nexport type { KeyboardNamespace, KeyboardEvents } from './namespaces/keyboard.js';\nexport type { HapticNamespace } from './namespaces/haptic.js';\nexport type { ClipboardNamespace } from './namespaces/clipboard.js';\nexport type { ScannerNamespace } from './namespaces/scanner.js';\nexport type { AuthNamespace } from './namespaces/auth.js';\nexport type { IAPNamespace } from './namespaces/iap.js';\nexport type { PushNamespace, PushEvents } from './namespaces/push.js';\nexport type {\n PermissionNamespace,\n PermissionType,\n PermissionStatus,\n} from './namespaces/permission.js';\nexport type { PreferenceNamespace } from './namespaces/preference.js';\nexport type { NavigationNamespace } from './namespaces/navigation.js';\nexport type { BrowserNamespace } from './namespaces/browser.js';\n\n// Utilities\nexport { createMessageId, serialize, deserialize, tryImport, moduleNotInstalledError } from './utils.js';\n","let messageCounter = 0;\n\n/** Generate a unique message ID */\nexport function createMessageId(): string {\n messageCounter += 1;\n return `bt_${Date.now()}_${messageCounter}`;\n}\n\n/** Serialize a bridge message to string */\nexport function serialize<T>(data: T): string {\n return JSON.stringify(data);\n}\n\n/** Deserialize a bridge message from string */\nexport function deserialize<T>(data: string): T {\n return JSON.parse(data) as T;\n}\n\ndeclare const require: (id: string) => unknown;\n\n/** Try to require a module, returns null if not available (Metro compatible) */\nexport function tryImport<T>(moduleName: string): T | null {\n try {\n return require(moduleName) as T;\n } catch {\n return null;\n }\n}\n\n/** Create a \"module not installed\" error response */\nexport function moduleNotInstalledError(moduleName: string): {\n success: false;\n error: string;\n} {\n return {\n success: false,\n error: `MODULE_NOT_INSTALLED: ${moduleName}`,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAI,iBAAiB;AAGd,SAAS,kBAA0B;AACxC,oBAAkB;AAClB,SAAO,MAAM,KAAK,IAAI,CAAC,IAAI,cAAc;AAC3C;AAGO,SAAS,UAAa,MAAiB;AAC5C,SAAO,KAAK,UAAU,IAAI;AAC5B;AAGO,SAAS,YAAe,MAAiB;AAC9C,SAAO,KAAK,MAAM,IAAI;AACxB;AAKO,SAAS,UAAa,YAA8B;AACzD,MAAI;AACF,WAAO,QAAQ,UAAU;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,wBAAwB,YAGtC;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,yBAAyB,UAAU;AAAA,EAC5C;AACF;","names":[]}
@@ -0,0 +1,563 @@
1
+ /** Base type for a bridge action with request and response */
2
+ interface BridgeAction<TRequest = unknown, TResponse = unknown> {
3
+ request: TRequest;
4
+ response: TResponse;
5
+ }
6
+ /** A namespace is a collection of actions */
7
+ type BridgeNamespace = Record<string, BridgeAction>;
8
+ /** The full bridge schema maps namespace.action strings to their types */
9
+ type BridgeSchema = Record<string, BridgeAction>;
10
+ /** Extract the request type for a given action key */
11
+ type BridgeRequest<S extends BridgeSchema, K extends keyof S> = S[K]['request'];
12
+ /** Extract the response type for a given action key */
13
+ type BridgeResponse<S extends BridgeSchema, K extends keyof S> = S[K]['response'];
14
+ /** Bridge event payload type */
15
+ type BridgeEventMap = Record<string, unknown>;
16
+ /** Bridge message envelope sent over postMessage */
17
+ interface BridgeMessage<T = unknown> {
18
+ id: string;
19
+ action: string;
20
+ payload: T;
21
+ timestamp: number;
22
+ }
23
+ /** Bridge response envelope */
24
+ interface BridgeResponseMessage<T = unknown> {
25
+ id: string;
26
+ action: string;
27
+ payload: T;
28
+ error?: string;
29
+ timestamp: number;
30
+ }
31
+ /** Bridge event message (Native → Web push) */
32
+ interface BridgeEventMessage<T = unknown> {
33
+ type: 'event';
34
+ event: string;
35
+ data: T;
36
+ timestamp: number;
37
+ }
38
+ /** Handler function type for expo side */
39
+ type BridgeHandler<TRequest, TResponse> = (payload: TRequest) => Promise<TResponse> | TResponse;
40
+ /** Map of action keys to handler functions */
41
+ type BridgeHandlerMap<S extends BridgeSchema> = {
42
+ [K in keyof S]?: BridgeHandler<S[K]['request'], S[K]['response']>;
43
+ };
44
+ /** Options for createDefaultHandlers */
45
+ type HandlerOptions = {
46
+ [K in NamespaceKey]?: boolean;
47
+ };
48
+ /** All 17 namespace keys */
49
+ type NamespaceKey = 'camera' | 'location' | 'file' | 'share' | 'device' | 'statusbar' | 'keyboard' | 'haptic' | 'clipboard' | 'scanner' | 'auth' | 'iap' | 'push' | 'permission' | 'preference' | 'navigation' | 'browser';
50
+
51
+ interface CameraNamespace {
52
+ 'camera.take': {
53
+ request: {
54
+ quality?: number;
55
+ facing?: 'front' | 'back';
56
+ allowsEditing?: boolean;
57
+ maxWidth?: number;
58
+ maxHeight?: number;
59
+ };
60
+ response: {
61
+ success: boolean;
62
+ uri?: string;
63
+ width?: number;
64
+ height?: number;
65
+ fileSize?: number;
66
+ mimeType?: string;
67
+ base64?: string;
68
+ };
69
+ };
70
+ 'camera.pickImage': {
71
+ request: {
72
+ allowsMultipleSelection?: boolean;
73
+ quality?: number;
74
+ mediaTypes?: 'images' | 'videos' | 'all';
75
+ maxCount?: number;
76
+ };
77
+ response: {
78
+ success: boolean;
79
+ assets: Array<{
80
+ uri: string;
81
+ width: number;
82
+ height: number;
83
+ fileSize?: number;
84
+ mimeType?: string;
85
+ }>;
86
+ };
87
+ };
88
+ }
89
+
90
+ interface LocationNamespace {
91
+ 'location.getCurrent': {
92
+ request: {
93
+ accuracy?: 'lowest' | 'low' | 'balanced' | 'high' | 'highest';
94
+ };
95
+ response: {
96
+ lat: number;
97
+ lng: number;
98
+ altitude?: number;
99
+ accuracy?: number;
100
+ timestamp: number;
101
+ };
102
+ };
103
+ 'location.watchStart': {
104
+ request: {
105
+ accuracy?: 'low' | 'balanced' | 'high';
106
+ distanceInterval?: number;
107
+ timeInterval?: number;
108
+ };
109
+ response: {
110
+ watchId: string;
111
+ };
112
+ };
113
+ 'location.watchStop': {
114
+ request: {
115
+ watchId: string;
116
+ };
117
+ response: {
118
+ success: boolean;
119
+ };
120
+ };
121
+ }
122
+ interface LocationEvents {
123
+ 'location.update': {
124
+ watchId: string;
125
+ lat: number;
126
+ lng: number;
127
+ altitude?: number;
128
+ accuracy?: number;
129
+ timestamp: number;
130
+ };
131
+ }
132
+
133
+ interface FileNamespace {
134
+ 'file.download': {
135
+ request: {
136
+ url: string;
137
+ filename: string;
138
+ saveToGallery?: boolean;
139
+ };
140
+ response: {
141
+ success: boolean;
142
+ localUri?: string;
143
+ error?: string;
144
+ };
145
+ };
146
+ 'file.read': {
147
+ request: {
148
+ uri: string;
149
+ encoding?: 'utf8' | 'base64';
150
+ };
151
+ response: {
152
+ success: boolean;
153
+ content?: string;
154
+ error?: string;
155
+ };
156
+ };
157
+ 'file.write': {
158
+ request: {
159
+ filename: string;
160
+ content: string;
161
+ encoding?: 'utf8' | 'base64';
162
+ directory?: 'document' | 'cache' | 'temp';
163
+ };
164
+ response: {
165
+ success: boolean;
166
+ uri?: string;
167
+ error?: string;
168
+ };
169
+ };
170
+ 'file.pick': {
171
+ request: {
172
+ type?: string[];
173
+ multiple?: boolean;
174
+ };
175
+ response: {
176
+ success: boolean;
177
+ files: Array<{
178
+ uri: string;
179
+ name: string;
180
+ size: number;
181
+ mimeType: string;
182
+ }>;
183
+ };
184
+ };
185
+ }
186
+
187
+ interface ShareNamespace {
188
+ 'share.open': {
189
+ request: {
190
+ url?: string;
191
+ title?: string;
192
+ message?: string;
193
+ };
194
+ response: {
195
+ success: boolean;
196
+ activityType?: string;
197
+ };
198
+ };
199
+ }
200
+
201
+ interface DeviceNamespace {
202
+ 'device.getInfo': {
203
+ request: Record<string, never>;
204
+ response: {
205
+ os: 'ios' | 'android';
206
+ osVersion: string;
207
+ model: string;
208
+ brand: string;
209
+ isTablet: boolean;
210
+ appVersion: string;
211
+ buildNumber: string;
212
+ bundleId: string;
213
+ };
214
+ };
215
+ 'device.getBattery': {
216
+ request: Record<string, never>;
217
+ response: {
218
+ level: number;
219
+ isCharging: boolean;
220
+ };
221
+ };
222
+ 'device.getNetwork': {
223
+ request: Record<string, never>;
224
+ response: {
225
+ type: 'wifi' | 'cellular' | 'none' | 'unknown';
226
+ isConnected: boolean;
227
+ };
228
+ };
229
+ }
230
+
231
+ interface StatusBarNamespace {
232
+ 'statusbar.setStyle': {
233
+ request: {
234
+ style: 'light' | 'dark' | 'auto';
235
+ };
236
+ response: {
237
+ success: boolean;
238
+ };
239
+ };
240
+ 'statusbar.setBackgroundColor': {
241
+ request: {
242
+ color: string;
243
+ animated?: boolean;
244
+ };
245
+ response: {
246
+ success: boolean;
247
+ };
248
+ };
249
+ 'statusbar.setHidden': {
250
+ request: {
251
+ hidden: boolean;
252
+ animation?: 'fade' | 'slide' | 'none';
253
+ };
254
+ response: {
255
+ success: boolean;
256
+ };
257
+ };
258
+ }
259
+
260
+ interface KeyboardNamespace {
261
+ 'keyboard.dismiss': {
262
+ request: Record<string, never>;
263
+ response: {
264
+ success: boolean;
265
+ };
266
+ };
267
+ 'keyboard.getState': {
268
+ request: Record<string, never>;
269
+ response: {
270
+ visible: boolean;
271
+ height: number;
272
+ };
273
+ };
274
+ }
275
+ interface KeyboardEvents {
276
+ 'keyboard.change': {
277
+ visible: boolean;
278
+ height: number;
279
+ animationDuration?: number;
280
+ };
281
+ }
282
+
283
+ interface HapticNamespace {
284
+ 'haptic.impact': {
285
+ request: {
286
+ style: 'light' | 'medium' | 'heavy';
287
+ };
288
+ response: void;
289
+ };
290
+ 'haptic.notification': {
291
+ request: {
292
+ type: 'success' | 'warning' | 'error';
293
+ };
294
+ response: void;
295
+ };
296
+ 'haptic.selection': {
297
+ request: Record<string, never>;
298
+ response: void;
299
+ };
300
+ }
301
+
302
+ interface ClipboardNamespace {
303
+ 'clipboard.copy': {
304
+ request: {
305
+ text: string;
306
+ };
307
+ response: {
308
+ success: boolean;
309
+ };
310
+ };
311
+ 'clipboard.paste': {
312
+ request: Record<string, never>;
313
+ response: {
314
+ text: string;
315
+ hasContent: boolean;
316
+ };
317
+ };
318
+ }
319
+
320
+ interface ScannerNamespace {
321
+ 'scanner.scanQR': {
322
+ request: {
323
+ prompt?: string;
324
+ };
325
+ response: {
326
+ success: boolean;
327
+ data?: string;
328
+ type?: string;
329
+ cancelled?: boolean;
330
+ };
331
+ };
332
+ }
333
+
334
+ interface AuthNamespace {
335
+ 'auth.biometric': {
336
+ request: {
337
+ promptMessage?: string;
338
+ cancelLabel?: string;
339
+ fallbackLabel?: string;
340
+ };
341
+ response: {
342
+ success: boolean;
343
+ error?: string;
344
+ biometryType?: 'fingerprint' | 'facial' | 'iris';
345
+ };
346
+ };
347
+ 'auth.isBiometricAvailable': {
348
+ request: Record<string, never>;
349
+ response: {
350
+ available: boolean;
351
+ biometryType?: 'fingerprint' | 'facial' | 'iris';
352
+ };
353
+ };
354
+ }
355
+
356
+ interface IAPNamespace {
357
+ 'iap.getProducts': {
358
+ request: {
359
+ productIds: string[];
360
+ };
361
+ response: {
362
+ products: Array<{
363
+ id: string;
364
+ title: string;
365
+ description: string;
366
+ price: string;
367
+ currency: string;
368
+ }>;
369
+ };
370
+ };
371
+ 'iap.purchase': {
372
+ request: {
373
+ productId: string;
374
+ };
375
+ response: {
376
+ success: boolean;
377
+ transactionId?: string;
378
+ receipt?: string;
379
+ error?: string;
380
+ };
381
+ };
382
+ 'iap.restore': {
383
+ request: Record<string, never>;
384
+ response: {
385
+ purchases: Array<{
386
+ productId: string;
387
+ transactionId: string;
388
+ }>;
389
+ };
390
+ };
391
+ }
392
+
393
+ interface PushNamespace {
394
+ 'push.getToken': {
395
+ request: Record<string, never>;
396
+ response: {
397
+ token: string;
398
+ platform: 'apns' | 'fcm';
399
+ };
400
+ };
401
+ 'push.requestPermission': {
402
+ request: Record<string, never>;
403
+ response: {
404
+ granted: boolean;
405
+ status: 'granted' | 'denied' | 'undetermined';
406
+ };
407
+ };
408
+ }
409
+ interface PushEvents {
410
+ 'push.received': {
411
+ title?: string;
412
+ body?: string;
413
+ data?: Record<string, unknown>;
414
+ };
415
+ 'push.tapped': {
416
+ title?: string;
417
+ body?: string;
418
+ data?: Record<string, unknown>;
419
+ };
420
+ }
421
+
422
+ type PermissionType = 'camera' | 'location' | 'microphone' | 'notifications' | 'mediaLibrary' | 'contacts' | 'calendar';
423
+ type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'limited';
424
+ interface PermissionNamespace {
425
+ 'permission.check': {
426
+ request: {
427
+ permission: PermissionType;
428
+ };
429
+ response: {
430
+ status: PermissionStatus;
431
+ canAskAgain: boolean;
432
+ };
433
+ };
434
+ 'permission.request': {
435
+ request: {
436
+ permission: PermissionType;
437
+ };
438
+ response: {
439
+ status: PermissionStatus;
440
+ canAskAgain: boolean;
441
+ };
442
+ };
443
+ 'permission.openSettings': {
444
+ request: Record<string, never>;
445
+ response: {
446
+ success: boolean;
447
+ };
448
+ };
449
+ }
450
+
451
+ interface PreferenceNamespace {
452
+ 'preference.get': {
453
+ request: {
454
+ key: string;
455
+ };
456
+ response: {
457
+ value: string | null;
458
+ };
459
+ };
460
+ 'preference.set': {
461
+ request: {
462
+ key: string;
463
+ value: string;
464
+ };
465
+ response: {
466
+ success: boolean;
467
+ };
468
+ };
469
+ 'preference.remove': {
470
+ request: {
471
+ key: string;
472
+ };
473
+ response: {
474
+ success: boolean;
475
+ };
476
+ };
477
+ 'preference.clear': {
478
+ request: Record<string, never>;
479
+ response: {
480
+ success: boolean;
481
+ };
482
+ };
483
+ }
484
+
485
+ interface NavigationNamespace {
486
+ 'navigation.goBack': {
487
+ request: Record<string, never>;
488
+ response: {
489
+ success: boolean;
490
+ };
491
+ };
492
+ 'navigation.push': {
493
+ request: {
494
+ url: string;
495
+ title?: string;
496
+ };
497
+ response: {
498
+ success: boolean;
499
+ };
500
+ };
501
+ 'navigation.close': {
502
+ request: Record<string, never>;
503
+ response: {
504
+ success: boolean;
505
+ };
506
+ };
507
+ 'navigation.setSwipeBack': {
508
+ request: {
509
+ enabled: boolean;
510
+ };
511
+ response: {
512
+ success: boolean;
513
+ };
514
+ };
515
+ }
516
+
517
+ interface BrowserNamespace {
518
+ 'browser.openExternal': {
519
+ request: {
520
+ url: string;
521
+ };
522
+ response: {
523
+ success: boolean;
524
+ };
525
+ };
526
+ 'browser.openInternal': {
527
+ request: {
528
+ url: string;
529
+ showTitle?: boolean;
530
+ toolbarColor?: string;
531
+ };
532
+ response: {
533
+ success: boolean;
534
+ };
535
+ };
536
+ }
537
+
538
+ /** Combined bridge schema with all 17 namespaces */
539
+ interface BridgeToolsSchema extends CameraNamespace, LocationNamespace, FileNamespace, ShareNamespace, DeviceNamespace, StatusBarNamespace, KeyboardNamespace, HapticNamespace, ClipboardNamespace, ScannerNamespace, AuthNamespace, IAPNamespace, PushNamespace, PermissionNamespace, PreferenceNamespace, NavigationNamespace, BrowserNamespace {
540
+ }
541
+ /** All action keys in the bridge schema */
542
+ type BridgeToolsAction = keyof BridgeToolsSchema;
543
+ /** Combined event types from all namespaces */
544
+ interface BridgeToolsEvents extends LocationEvents, KeyboardEvents, PushEvents {
545
+ }
546
+ /** All event names */
547
+ type BridgeToolsEvent = keyof BridgeToolsEvents;
548
+
549
+ /** Generate a unique message ID */
550
+ declare function createMessageId(): string;
551
+ /** Serialize a bridge message to string */
552
+ declare function serialize<T>(data: T): string;
553
+ /** Deserialize a bridge message from string */
554
+ declare function deserialize<T>(data: string): T;
555
+ /** Try to require a module, returns null if not available (Metro compatible) */
556
+ declare function tryImport<T>(moduleName: string): T | null;
557
+ /** Create a "module not installed" error response */
558
+ declare function moduleNotInstalledError(moduleName: string): {
559
+ success: false;
560
+ error: string;
561
+ };
562
+
563
+ export { type AuthNamespace, type BridgeAction, type BridgeEventMap, type BridgeEventMessage, type BridgeHandler, type BridgeHandlerMap, type BridgeMessage, type BridgeNamespace, type BridgeRequest, type BridgeResponse, type BridgeResponseMessage, type BridgeSchema, type BridgeToolsAction, type BridgeToolsEvent, type BridgeToolsEvents, type BridgeToolsSchema, type BrowserNamespace, type CameraNamespace, type ClipboardNamespace, type DeviceNamespace, type FileNamespace, type HandlerOptions, type HapticNamespace, type IAPNamespace, type KeyboardEvents, type KeyboardNamespace, type LocationEvents, type LocationNamespace, type NamespaceKey, type NavigationNamespace, type PermissionNamespace, type PermissionStatus, type PermissionType, type PreferenceNamespace, type PushEvents, type PushNamespace, type ScannerNamespace, type ShareNamespace, type StatusBarNamespace, createMessageId, deserialize, moduleNotInstalledError, serialize, tryImport };
@@ -0,0 +1,563 @@
1
+ /** Base type for a bridge action with request and response */
2
+ interface BridgeAction<TRequest = unknown, TResponse = unknown> {
3
+ request: TRequest;
4
+ response: TResponse;
5
+ }
6
+ /** A namespace is a collection of actions */
7
+ type BridgeNamespace = Record<string, BridgeAction>;
8
+ /** The full bridge schema maps namespace.action strings to their types */
9
+ type BridgeSchema = Record<string, BridgeAction>;
10
+ /** Extract the request type for a given action key */
11
+ type BridgeRequest<S extends BridgeSchema, K extends keyof S> = S[K]['request'];
12
+ /** Extract the response type for a given action key */
13
+ type BridgeResponse<S extends BridgeSchema, K extends keyof S> = S[K]['response'];
14
+ /** Bridge event payload type */
15
+ type BridgeEventMap = Record<string, unknown>;
16
+ /** Bridge message envelope sent over postMessage */
17
+ interface BridgeMessage<T = unknown> {
18
+ id: string;
19
+ action: string;
20
+ payload: T;
21
+ timestamp: number;
22
+ }
23
+ /** Bridge response envelope */
24
+ interface BridgeResponseMessage<T = unknown> {
25
+ id: string;
26
+ action: string;
27
+ payload: T;
28
+ error?: string;
29
+ timestamp: number;
30
+ }
31
+ /** Bridge event message (Native → Web push) */
32
+ interface BridgeEventMessage<T = unknown> {
33
+ type: 'event';
34
+ event: string;
35
+ data: T;
36
+ timestamp: number;
37
+ }
38
+ /** Handler function type for expo side */
39
+ type BridgeHandler<TRequest, TResponse> = (payload: TRequest) => Promise<TResponse> | TResponse;
40
+ /** Map of action keys to handler functions */
41
+ type BridgeHandlerMap<S extends BridgeSchema> = {
42
+ [K in keyof S]?: BridgeHandler<S[K]['request'], S[K]['response']>;
43
+ };
44
+ /** Options for createDefaultHandlers */
45
+ type HandlerOptions = {
46
+ [K in NamespaceKey]?: boolean;
47
+ };
48
+ /** All 17 namespace keys */
49
+ type NamespaceKey = 'camera' | 'location' | 'file' | 'share' | 'device' | 'statusbar' | 'keyboard' | 'haptic' | 'clipboard' | 'scanner' | 'auth' | 'iap' | 'push' | 'permission' | 'preference' | 'navigation' | 'browser';
50
+
51
+ interface CameraNamespace {
52
+ 'camera.take': {
53
+ request: {
54
+ quality?: number;
55
+ facing?: 'front' | 'back';
56
+ allowsEditing?: boolean;
57
+ maxWidth?: number;
58
+ maxHeight?: number;
59
+ };
60
+ response: {
61
+ success: boolean;
62
+ uri?: string;
63
+ width?: number;
64
+ height?: number;
65
+ fileSize?: number;
66
+ mimeType?: string;
67
+ base64?: string;
68
+ };
69
+ };
70
+ 'camera.pickImage': {
71
+ request: {
72
+ allowsMultipleSelection?: boolean;
73
+ quality?: number;
74
+ mediaTypes?: 'images' | 'videos' | 'all';
75
+ maxCount?: number;
76
+ };
77
+ response: {
78
+ success: boolean;
79
+ assets: Array<{
80
+ uri: string;
81
+ width: number;
82
+ height: number;
83
+ fileSize?: number;
84
+ mimeType?: string;
85
+ }>;
86
+ };
87
+ };
88
+ }
89
+
90
+ interface LocationNamespace {
91
+ 'location.getCurrent': {
92
+ request: {
93
+ accuracy?: 'lowest' | 'low' | 'balanced' | 'high' | 'highest';
94
+ };
95
+ response: {
96
+ lat: number;
97
+ lng: number;
98
+ altitude?: number;
99
+ accuracy?: number;
100
+ timestamp: number;
101
+ };
102
+ };
103
+ 'location.watchStart': {
104
+ request: {
105
+ accuracy?: 'low' | 'balanced' | 'high';
106
+ distanceInterval?: number;
107
+ timeInterval?: number;
108
+ };
109
+ response: {
110
+ watchId: string;
111
+ };
112
+ };
113
+ 'location.watchStop': {
114
+ request: {
115
+ watchId: string;
116
+ };
117
+ response: {
118
+ success: boolean;
119
+ };
120
+ };
121
+ }
122
+ interface LocationEvents {
123
+ 'location.update': {
124
+ watchId: string;
125
+ lat: number;
126
+ lng: number;
127
+ altitude?: number;
128
+ accuracy?: number;
129
+ timestamp: number;
130
+ };
131
+ }
132
+
133
+ interface FileNamespace {
134
+ 'file.download': {
135
+ request: {
136
+ url: string;
137
+ filename: string;
138
+ saveToGallery?: boolean;
139
+ };
140
+ response: {
141
+ success: boolean;
142
+ localUri?: string;
143
+ error?: string;
144
+ };
145
+ };
146
+ 'file.read': {
147
+ request: {
148
+ uri: string;
149
+ encoding?: 'utf8' | 'base64';
150
+ };
151
+ response: {
152
+ success: boolean;
153
+ content?: string;
154
+ error?: string;
155
+ };
156
+ };
157
+ 'file.write': {
158
+ request: {
159
+ filename: string;
160
+ content: string;
161
+ encoding?: 'utf8' | 'base64';
162
+ directory?: 'document' | 'cache' | 'temp';
163
+ };
164
+ response: {
165
+ success: boolean;
166
+ uri?: string;
167
+ error?: string;
168
+ };
169
+ };
170
+ 'file.pick': {
171
+ request: {
172
+ type?: string[];
173
+ multiple?: boolean;
174
+ };
175
+ response: {
176
+ success: boolean;
177
+ files: Array<{
178
+ uri: string;
179
+ name: string;
180
+ size: number;
181
+ mimeType: string;
182
+ }>;
183
+ };
184
+ };
185
+ }
186
+
187
+ interface ShareNamespace {
188
+ 'share.open': {
189
+ request: {
190
+ url?: string;
191
+ title?: string;
192
+ message?: string;
193
+ };
194
+ response: {
195
+ success: boolean;
196
+ activityType?: string;
197
+ };
198
+ };
199
+ }
200
+
201
+ interface DeviceNamespace {
202
+ 'device.getInfo': {
203
+ request: Record<string, never>;
204
+ response: {
205
+ os: 'ios' | 'android';
206
+ osVersion: string;
207
+ model: string;
208
+ brand: string;
209
+ isTablet: boolean;
210
+ appVersion: string;
211
+ buildNumber: string;
212
+ bundleId: string;
213
+ };
214
+ };
215
+ 'device.getBattery': {
216
+ request: Record<string, never>;
217
+ response: {
218
+ level: number;
219
+ isCharging: boolean;
220
+ };
221
+ };
222
+ 'device.getNetwork': {
223
+ request: Record<string, never>;
224
+ response: {
225
+ type: 'wifi' | 'cellular' | 'none' | 'unknown';
226
+ isConnected: boolean;
227
+ };
228
+ };
229
+ }
230
+
231
+ interface StatusBarNamespace {
232
+ 'statusbar.setStyle': {
233
+ request: {
234
+ style: 'light' | 'dark' | 'auto';
235
+ };
236
+ response: {
237
+ success: boolean;
238
+ };
239
+ };
240
+ 'statusbar.setBackgroundColor': {
241
+ request: {
242
+ color: string;
243
+ animated?: boolean;
244
+ };
245
+ response: {
246
+ success: boolean;
247
+ };
248
+ };
249
+ 'statusbar.setHidden': {
250
+ request: {
251
+ hidden: boolean;
252
+ animation?: 'fade' | 'slide' | 'none';
253
+ };
254
+ response: {
255
+ success: boolean;
256
+ };
257
+ };
258
+ }
259
+
260
+ interface KeyboardNamespace {
261
+ 'keyboard.dismiss': {
262
+ request: Record<string, never>;
263
+ response: {
264
+ success: boolean;
265
+ };
266
+ };
267
+ 'keyboard.getState': {
268
+ request: Record<string, never>;
269
+ response: {
270
+ visible: boolean;
271
+ height: number;
272
+ };
273
+ };
274
+ }
275
+ interface KeyboardEvents {
276
+ 'keyboard.change': {
277
+ visible: boolean;
278
+ height: number;
279
+ animationDuration?: number;
280
+ };
281
+ }
282
+
283
+ interface HapticNamespace {
284
+ 'haptic.impact': {
285
+ request: {
286
+ style: 'light' | 'medium' | 'heavy';
287
+ };
288
+ response: void;
289
+ };
290
+ 'haptic.notification': {
291
+ request: {
292
+ type: 'success' | 'warning' | 'error';
293
+ };
294
+ response: void;
295
+ };
296
+ 'haptic.selection': {
297
+ request: Record<string, never>;
298
+ response: void;
299
+ };
300
+ }
301
+
302
+ interface ClipboardNamespace {
303
+ 'clipboard.copy': {
304
+ request: {
305
+ text: string;
306
+ };
307
+ response: {
308
+ success: boolean;
309
+ };
310
+ };
311
+ 'clipboard.paste': {
312
+ request: Record<string, never>;
313
+ response: {
314
+ text: string;
315
+ hasContent: boolean;
316
+ };
317
+ };
318
+ }
319
+
320
+ interface ScannerNamespace {
321
+ 'scanner.scanQR': {
322
+ request: {
323
+ prompt?: string;
324
+ };
325
+ response: {
326
+ success: boolean;
327
+ data?: string;
328
+ type?: string;
329
+ cancelled?: boolean;
330
+ };
331
+ };
332
+ }
333
+
334
+ interface AuthNamespace {
335
+ 'auth.biometric': {
336
+ request: {
337
+ promptMessage?: string;
338
+ cancelLabel?: string;
339
+ fallbackLabel?: string;
340
+ };
341
+ response: {
342
+ success: boolean;
343
+ error?: string;
344
+ biometryType?: 'fingerprint' | 'facial' | 'iris';
345
+ };
346
+ };
347
+ 'auth.isBiometricAvailable': {
348
+ request: Record<string, never>;
349
+ response: {
350
+ available: boolean;
351
+ biometryType?: 'fingerprint' | 'facial' | 'iris';
352
+ };
353
+ };
354
+ }
355
+
356
+ interface IAPNamespace {
357
+ 'iap.getProducts': {
358
+ request: {
359
+ productIds: string[];
360
+ };
361
+ response: {
362
+ products: Array<{
363
+ id: string;
364
+ title: string;
365
+ description: string;
366
+ price: string;
367
+ currency: string;
368
+ }>;
369
+ };
370
+ };
371
+ 'iap.purchase': {
372
+ request: {
373
+ productId: string;
374
+ };
375
+ response: {
376
+ success: boolean;
377
+ transactionId?: string;
378
+ receipt?: string;
379
+ error?: string;
380
+ };
381
+ };
382
+ 'iap.restore': {
383
+ request: Record<string, never>;
384
+ response: {
385
+ purchases: Array<{
386
+ productId: string;
387
+ transactionId: string;
388
+ }>;
389
+ };
390
+ };
391
+ }
392
+
393
+ interface PushNamespace {
394
+ 'push.getToken': {
395
+ request: Record<string, never>;
396
+ response: {
397
+ token: string;
398
+ platform: 'apns' | 'fcm';
399
+ };
400
+ };
401
+ 'push.requestPermission': {
402
+ request: Record<string, never>;
403
+ response: {
404
+ granted: boolean;
405
+ status: 'granted' | 'denied' | 'undetermined';
406
+ };
407
+ };
408
+ }
409
+ interface PushEvents {
410
+ 'push.received': {
411
+ title?: string;
412
+ body?: string;
413
+ data?: Record<string, unknown>;
414
+ };
415
+ 'push.tapped': {
416
+ title?: string;
417
+ body?: string;
418
+ data?: Record<string, unknown>;
419
+ };
420
+ }
421
+
422
+ type PermissionType = 'camera' | 'location' | 'microphone' | 'notifications' | 'mediaLibrary' | 'contacts' | 'calendar';
423
+ type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'limited';
424
+ interface PermissionNamespace {
425
+ 'permission.check': {
426
+ request: {
427
+ permission: PermissionType;
428
+ };
429
+ response: {
430
+ status: PermissionStatus;
431
+ canAskAgain: boolean;
432
+ };
433
+ };
434
+ 'permission.request': {
435
+ request: {
436
+ permission: PermissionType;
437
+ };
438
+ response: {
439
+ status: PermissionStatus;
440
+ canAskAgain: boolean;
441
+ };
442
+ };
443
+ 'permission.openSettings': {
444
+ request: Record<string, never>;
445
+ response: {
446
+ success: boolean;
447
+ };
448
+ };
449
+ }
450
+
451
+ interface PreferenceNamespace {
452
+ 'preference.get': {
453
+ request: {
454
+ key: string;
455
+ };
456
+ response: {
457
+ value: string | null;
458
+ };
459
+ };
460
+ 'preference.set': {
461
+ request: {
462
+ key: string;
463
+ value: string;
464
+ };
465
+ response: {
466
+ success: boolean;
467
+ };
468
+ };
469
+ 'preference.remove': {
470
+ request: {
471
+ key: string;
472
+ };
473
+ response: {
474
+ success: boolean;
475
+ };
476
+ };
477
+ 'preference.clear': {
478
+ request: Record<string, never>;
479
+ response: {
480
+ success: boolean;
481
+ };
482
+ };
483
+ }
484
+
485
+ interface NavigationNamespace {
486
+ 'navigation.goBack': {
487
+ request: Record<string, never>;
488
+ response: {
489
+ success: boolean;
490
+ };
491
+ };
492
+ 'navigation.push': {
493
+ request: {
494
+ url: string;
495
+ title?: string;
496
+ };
497
+ response: {
498
+ success: boolean;
499
+ };
500
+ };
501
+ 'navigation.close': {
502
+ request: Record<string, never>;
503
+ response: {
504
+ success: boolean;
505
+ };
506
+ };
507
+ 'navigation.setSwipeBack': {
508
+ request: {
509
+ enabled: boolean;
510
+ };
511
+ response: {
512
+ success: boolean;
513
+ };
514
+ };
515
+ }
516
+
517
+ interface BrowserNamespace {
518
+ 'browser.openExternal': {
519
+ request: {
520
+ url: string;
521
+ };
522
+ response: {
523
+ success: boolean;
524
+ };
525
+ };
526
+ 'browser.openInternal': {
527
+ request: {
528
+ url: string;
529
+ showTitle?: boolean;
530
+ toolbarColor?: string;
531
+ };
532
+ response: {
533
+ success: boolean;
534
+ };
535
+ };
536
+ }
537
+
538
+ /** Combined bridge schema with all 17 namespaces */
539
+ interface BridgeToolsSchema extends CameraNamespace, LocationNamespace, FileNamespace, ShareNamespace, DeviceNamespace, StatusBarNamespace, KeyboardNamespace, HapticNamespace, ClipboardNamespace, ScannerNamespace, AuthNamespace, IAPNamespace, PushNamespace, PermissionNamespace, PreferenceNamespace, NavigationNamespace, BrowserNamespace {
540
+ }
541
+ /** All action keys in the bridge schema */
542
+ type BridgeToolsAction = keyof BridgeToolsSchema;
543
+ /** Combined event types from all namespaces */
544
+ interface BridgeToolsEvents extends LocationEvents, KeyboardEvents, PushEvents {
545
+ }
546
+ /** All event names */
547
+ type BridgeToolsEvent = keyof BridgeToolsEvents;
548
+
549
+ /** Generate a unique message ID */
550
+ declare function createMessageId(): string;
551
+ /** Serialize a bridge message to string */
552
+ declare function serialize<T>(data: T): string;
553
+ /** Deserialize a bridge message from string */
554
+ declare function deserialize<T>(data: string): T;
555
+ /** Try to require a module, returns null if not available (Metro compatible) */
556
+ declare function tryImport<T>(moduleName: string): T | null;
557
+ /** Create a "module not installed" error response */
558
+ declare function moduleNotInstalledError(moduleName: string): {
559
+ success: false;
560
+ error: string;
561
+ };
562
+
563
+ export { type AuthNamespace, type BridgeAction, type BridgeEventMap, type BridgeEventMessage, type BridgeHandler, type BridgeHandlerMap, type BridgeMessage, type BridgeNamespace, type BridgeRequest, type BridgeResponse, type BridgeResponseMessage, type BridgeSchema, type BridgeToolsAction, type BridgeToolsEvent, type BridgeToolsEvents, type BridgeToolsSchema, type BrowserNamespace, type CameraNamespace, type ClipboardNamespace, type DeviceNamespace, type FileNamespace, type HandlerOptions, type HapticNamespace, type IAPNamespace, type KeyboardEvents, type KeyboardNamespace, type LocationEvents, type LocationNamespace, type NamespaceKey, type NavigationNamespace, type PermissionNamespace, type PermissionStatus, type PermissionType, type PreferenceNamespace, type PushEvents, type PushNamespace, type ScannerNamespace, type ShareNamespace, type StatusBarNamespace, createMessageId, deserialize, moduleNotInstalledError, serialize, tryImport };
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/utils.ts
9
+ var messageCounter = 0;
10
+ function createMessageId() {
11
+ messageCounter += 1;
12
+ return `bt_${Date.now()}_${messageCounter}`;
13
+ }
14
+ function serialize(data) {
15
+ return JSON.stringify(data);
16
+ }
17
+ function deserialize(data) {
18
+ return JSON.parse(data);
19
+ }
20
+ function tryImport(moduleName) {
21
+ try {
22
+ return __require(moduleName);
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ function moduleNotInstalledError(moduleName) {
28
+ return {
29
+ success: false,
30
+ error: `MODULE_NOT_INSTALLED: ${moduleName}`
31
+ };
32
+ }
33
+ export {
34
+ createMessageId,
35
+ deserialize,
36
+ moduleNotInstalledError,
37
+ serialize,
38
+ tryImport
39
+ };
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["let messageCounter = 0;\n\n/** Generate a unique message ID */\nexport function createMessageId(): string {\n messageCounter += 1;\n return `bt_${Date.now()}_${messageCounter}`;\n}\n\n/** Serialize a bridge message to string */\nexport function serialize<T>(data: T): string {\n return JSON.stringify(data);\n}\n\n/** Deserialize a bridge message from string */\nexport function deserialize<T>(data: string): T {\n return JSON.parse(data) as T;\n}\n\ndeclare const require: (id: string) => unknown;\n\n/** Try to require a module, returns null if not available (Metro compatible) */\nexport function tryImport<T>(moduleName: string): T | null {\n try {\n return require(moduleName) as T;\n } catch {\n return null;\n }\n}\n\n/** Create a \"module not installed\" error response */\nexport function moduleNotInstalledError(moduleName: string): {\n success: false;\n error: string;\n} {\n return {\n success: false,\n error: `MODULE_NOT_INSTALLED: ${moduleName}`,\n };\n}\n"],"mappings":";;;;;;;;AAAA,IAAI,iBAAiB;AAGd,SAAS,kBAA0B;AACxC,oBAAkB;AAClB,SAAO,MAAM,KAAK,IAAI,CAAC,IAAI,cAAc;AAC3C;AAGO,SAAS,UAAa,MAAiB;AAC5C,SAAO,KAAK,UAAU,IAAI;AAC5B;AAGO,SAAS,YAAe,MAAiB;AAC9C,SAAO,KAAK,MAAM,IAAI;AACxB;AAKO,SAAS,UAAa,YAA8B;AACzD,MAAI;AACF,WAAO,UAAQ,UAAU;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,wBAAwB,YAGtC;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,yBAAyB,UAAU;AAAA,EAC5C;AACF;","names":[]}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@rn-bridge-tools/core",
3
+ "version": "1.0.0",
4
+ "description": "Shared types and utilities for bridge-tools SDK",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": ["dist"],
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "dev": "tsup --watch",
25
+ "test": "vitest run",
26
+ "lint": "eslint src/",
27
+ "typecheck": "tsc --noEmit",
28
+ "clean": "rm -rf dist"
29
+ },
30
+ "devDependencies": {
31
+ "tsup": "^8.3.0",
32
+ "typescript": "^5.7.0",
33
+ "vitest": "^2.1.0",
34
+ "eslint": "^9.0.0"
35
+ }
36
+ }