@amabeth/repeating-wheel-picker 1.0.0 → 1.2.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.
Files changed (258) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +57 -44
  3. package/example/index.ts +8 -0
  4. package/example/node_modules/@expo/cli/static/template/+html.tsx +28 -0
  5. package/example/node_modules/@expo/cli/static/template/+native-intent.ts +9 -0
  6. package/example/node_modules/@expo/cli/static/template/[...rsc]+api.ts +16 -0
  7. package/example/node_modules/ansi-styles/index.d.ts +345 -0
  8. package/example/node_modules/chalk/index.d.ts +415 -0
  9. package/example/node_modules/commander/typings/index.d.ts +627 -0
  10. package/example/node_modules/expo/Expo.podspec +108 -0
  11. package/example/node_modules/expo/build/Expo.d.ts +8 -0
  12. package/example/node_modules/expo/build/Expo.fx.d.ts +4 -0
  13. package/example/node_modules/expo/build/Expo.fx.web.d.ts +3 -0
  14. package/example/node_modules/expo/build/devtools/DevToolsPluginClient.d.ts +72 -0
  15. package/example/node_modules/expo/build/devtools/DevToolsPluginClientFactory.d.ts +16 -0
  16. package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplApp.d.ts +15 -0
  17. package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplBrowser.d.ts +14 -0
  18. package/example/node_modules/expo/build/devtools/MessageFramePacker.d.ts +50 -0
  19. package/example/node_modules/expo/build/devtools/ProtocolVersion.d.ts +7 -0
  20. package/example/node_modules/expo/build/devtools/WebSocketBackingStore.d.ts +10 -0
  21. package/example/node_modules/expo/build/devtools/WebSocketWithReconnect.d.ts +81 -0
  22. package/example/node_modules/expo/build/devtools/devtools.types.d.ts +42 -0
  23. package/example/node_modules/expo/build/devtools/getConnectionInfo.d.ts +6 -0
  24. package/example/node_modules/expo/build/devtools/getConnectionInfo.native.d.ts +6 -0
  25. package/example/node_modules/expo/build/devtools/index.d.ts +12 -0
  26. package/example/node_modules/expo/build/devtools/logger.d.ts +6 -0
  27. package/example/node_modules/expo/build/dom/base.d.ts +5 -0
  28. package/example/node_modules/expo/build/dom/dom-entry.d.ts +3 -0
  29. package/example/node_modules/expo/build/dom/dom-hooks.d.ts +8 -0
  30. package/example/node_modules/expo/build/dom/dom.d.ts +5 -0
  31. package/example/node_modules/expo/build/dom/dom.types.d.ts +34 -0
  32. package/example/node_modules/expo/build/dom/dom.web.d.ts +3 -0
  33. package/example/node_modules/expo/build/dom/global-events.d.ts +4 -0
  34. package/example/node_modules/expo/build/dom/injection.d.ts +9 -0
  35. package/example/node_modules/expo/build/dom/internal.d.ts +3 -0
  36. package/example/node_modules/expo/build/dom/internal.web.d.ts +2 -0
  37. package/example/node_modules/expo/build/dom/marshal.d.ts +4 -0
  38. package/example/node_modules/expo/build/dom/webview/ExpoDOMWebView.d.ts +6 -0
  39. package/example/node_modules/expo/build/dom/webview/RNWebView.d.ts +7 -0
  40. package/example/node_modules/expo/build/dom/webview/useDebugZeroHeight.d.ts +12 -0
  41. package/example/node_modules/expo/build/dom/webview-wrapper.d.ts +16 -0
  42. package/example/node_modules/expo/build/environment/DevLoadingView.d.ts +3 -0
  43. package/example/node_modules/expo/build/environment/DevLoadingView.web.d.ts +3 -0
  44. package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.d.ts +9 -0
  45. package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.native.d.ts +3 -0
  46. package/example/node_modules/expo/build/environment/ExpoGo.d.ts +31 -0
  47. package/example/node_modules/expo/build/environment/ExpoGo.web.d.ts +3 -0
  48. package/example/node_modules/expo/build/environment/getInitialSafeArea.d.ts +7 -0
  49. package/example/node_modules/expo/build/environment/getInitialSafeArea.native.d.ts +11 -0
  50. package/example/node_modules/expo/build/errors/AppEntryNotFound.d.ts +2 -0
  51. package/example/node_modules/expo/build/errors/ExpoErrorManager.d.ts +8 -0
  52. package/example/node_modules/expo/build/errors/ExpoErrorManager.native.d.ts +4 -0
  53. package/example/node_modules/expo/build/hooks/useEvent.d.ts +59 -0
  54. package/example/node_modules/expo/build/launch/registerRootComponent.d.ts +30 -0
  55. package/example/node_modules/expo/build/launch/withDevTools.d.ts +3 -0
  56. package/example/node_modules/expo/build/launch/withDevTools.ios.d.ts +7 -0
  57. package/example/node_modules/expo/build/launch/withDevTools.web.d.ts +3 -0
  58. package/example/node_modules/expo/build/timer/polyfillNextTick.d.ts +6 -0
  59. package/example/node_modules/expo/build/utils/blobUtils.d.ts +9 -0
  60. package/example/node_modules/expo/build/utils/getBundleUrl.d.ts +2 -0
  61. package/example/node_modules/expo/build/utils/getBundleUrl.native.d.ts +2 -0
  62. package/example/node_modules/expo/build/utils/getBundleUrl.web.d.ts +2 -0
  63. package/example/node_modules/expo/build/winter/FormData.d.ts +49 -0
  64. package/example/node_modules/expo/build/winter/ImportMetaRegistry.d.ts +9 -0
  65. package/example/node_modules/expo/build/winter/TextDecoder.d.ts +20 -0
  66. package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.d.ts +2 -0
  67. package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.web.d.ts +10 -0
  68. package/example/node_modules/expo/build/winter/fetch/FetchErrors.d.ts +8 -0
  69. package/example/node_modules/expo/build/winter/fetch/FetchResponse.d.ts +31 -0
  70. package/example/node_modules/expo/build/winter/fetch/NativeRequest.d.ts +30 -0
  71. package/example/node_modules/expo/build/winter/fetch/RequestUtils.d.ts +21 -0
  72. package/example/node_modules/expo/build/winter/fetch/convertFormData.d.ts +19 -0
  73. package/example/node_modules/expo/build/winter/fetch/fetch.d.ts +4 -0
  74. package/example/node_modules/expo/build/winter/fetch/fetch.types.d.ts +16 -0
  75. package/example/node_modules/expo/build/winter/fetch/fetch.web.d.ts +2 -0
  76. package/example/node_modules/expo/build/winter/fetch/index.d.ts +3 -0
  77. package/example/node_modules/expo/build/winter/index.d.ts +2 -0
  78. package/example/node_modules/expo/build/winter/runtime.d.ts +2 -0
  79. package/example/node_modules/expo/build/winter/runtime.native.d.ts +2 -0
  80. package/example/node_modules/expo/build/winter/url.d.ts +23 -0
  81. package/example/node_modules/expo/config-plugins.d.ts +1 -0
  82. package/example/node_modules/expo/config.d.ts +1 -0
  83. package/example/node_modules/expo/devtools.d.ts +1 -0
  84. package/example/node_modules/expo/dom/global.d.ts +1 -0
  85. package/example/node_modules/expo/dom/index.d.ts +1 -0
  86. package/example/node_modules/expo/dom/internal.d.ts +1 -0
  87. package/example/node_modules/expo/fetch.d.ts +1 -0
  88. package/example/node_modules/expo/fingerprint.d.ts +1 -0
  89. package/example/node_modules/expo/metro-config.d.ts +1 -0
  90. package/example/node_modules/expo/react-native.config.js +50 -0
  91. package/example/node_modules/expo/src/Expo.fx.tsx +53 -0
  92. package/example/node_modules/expo/src/Expo.fx.web.tsx +21 -0
  93. package/example/node_modules/expo/src/Expo.ts +30 -0
  94. package/example/node_modules/expo/src/devtools/DevToolsPluginClient.ts +240 -0
  95. package/example/node_modules/expo/src/devtools/DevToolsPluginClientFactory.ts +73 -0
  96. package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplApp.ts +56 -0
  97. package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplBrowser.ts +38 -0
  98. package/example/node_modules/expo/src/devtools/MessageFramePacker.ts +235 -0
  99. package/example/node_modules/expo/src/devtools/ProtocolVersion.ts +6 -0
  100. package/example/node_modules/expo/src/devtools/WebSocketBackingStore.ts +10 -0
  101. package/example/node_modules/expo/src/devtools/WebSocketWithReconnect.ts +318 -0
  102. package/example/node_modules/expo/src/devtools/devtools.types.ts +50 -0
  103. package/example/node_modules/expo/src/devtools/getConnectionInfo.native.ts +18 -0
  104. package/example/node_modules/expo/src/devtools/getConnectionInfo.ts +16 -0
  105. package/example/node_modules/expo/src/devtools/index.ts +53 -0
  106. package/example/node_modules/expo/src/devtools/logger.ts +29 -0
  107. package/example/node_modules/expo/src/dom/base.ts +62 -0
  108. package/example/node_modules/expo/src/dom/dom-entry.tsx +128 -0
  109. package/example/node_modules/expo/src/dom/dom-hooks.ts +46 -0
  110. package/example/node_modules/expo/src/dom/dom.ts +8 -0
  111. package/example/node_modules/expo/src/dom/dom.types.ts +39 -0
  112. package/example/node_modules/expo/src/dom/dom.web.ts +6 -0
  113. package/example/node_modules/expo/src/dom/global-events.ts +16 -0
  114. package/example/node_modules/expo/src/dom/injection.ts +42 -0
  115. package/example/node_modules/expo/src/dom/internal.ts +5 -0
  116. package/example/node_modules/expo/src/dom/internal.web.ts +1 -0
  117. package/example/node_modules/expo/src/dom/marshal.tsx +116 -0
  118. package/example/node_modules/expo/src/dom/webview/ExpoDOMWebView.ts +10 -0
  119. package/example/node_modules/expo/src/dom/webview/RNWebView.ts +12 -0
  120. package/example/node_modules/expo/src/dom/webview/useDebugZeroHeight.ts +62 -0
  121. package/example/node_modules/expo/src/dom/webview-wrapper.tsx +253 -0
  122. package/example/node_modules/expo/src/environment/DevLoadingView.tsx +123 -0
  123. package/example/node_modules/expo/src/environment/DevLoadingView.web.tsx +135 -0
  124. package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.native.ts +3 -0
  125. package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.ts +7 -0
  126. package/example/node_modules/expo/src/environment/ExpoGo.ts +53 -0
  127. package/example/node_modules/expo/src/environment/ExpoGo.web.ts +7 -0
  128. package/example/node_modules/expo/src/environment/getInitialSafeArea.native.ts +16 -0
  129. package/example/node_modules/expo/src/environment/getInitialSafeArea.ts +8 -0
  130. package/example/node_modules/expo/src/errors/AppEntryNotFound.tsx +35 -0
  131. package/example/node_modules/expo/src/errors/ExpoErrorManager.native.ts +51 -0
  132. package/example/node_modules/expo/src/errors/ExpoErrorManager.ts +11 -0
  133. package/example/node_modules/expo/src/hooks/useEvent.ts +112 -0
  134. package/example/node_modules/expo/src/launch/registerRootComponent.tsx +64 -0
  135. package/example/node_modules/expo/src/launch/withDevTools.ios.tsx +47 -0
  136. package/example/node_modules/expo/src/launch/withDevTools.tsx +30 -0
  137. package/example/node_modules/expo/src/launch/withDevTools.web.tsx +23 -0
  138. package/example/node_modules/expo/src/timer/polyfillNextTick.ts +10 -0
  139. package/example/node_modules/expo/src/ts-declarations/console.d.ts +47 -0
  140. package/example/node_modules/expo/src/ts-declarations/global.d.ts +12 -0
  141. package/example/node_modules/expo/src/ts-declarations/react-native.d.ts +34 -0
  142. package/example/node_modules/expo/src/ts-declarations/whatwg-url-without-unicode.d.ts +186 -0
  143. package/example/node_modules/expo/src/utils/blobUtils.ts +23 -0
  144. package/example/node_modules/expo/src/utils/getBundleUrl.native.ts +17 -0
  145. package/example/node_modules/expo/src/utils/getBundleUrl.ts +5 -0
  146. package/example/node_modules/expo/src/utils/getBundleUrl.web.ts +21 -0
  147. package/example/node_modules/expo/src/winter/FormData.ts +222 -0
  148. package/example/node_modules/expo/src/winter/ImportMetaRegistry.ts +14 -0
  149. package/example/node_modules/expo/src/winter/TextDecoder.ts +429 -0
  150. package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.ts +3 -0
  151. package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.web.ts +7 -0
  152. package/example/node_modules/expo/src/winter/fetch/FetchErrors.ts +11 -0
  153. package/example/node_modules/expo/src/winter/fetch/FetchResponse.ts +146 -0
  154. package/example/node_modules/expo/src/winter/fetch/NativeRequest.ts +38 -0
  155. package/example/node_modules/expo/src/winter/fetch/RequestUtils.ts +124 -0
  156. package/example/node_modules/expo/src/winter/fetch/convertFormData.ts +92 -0
  157. package/example/node_modules/expo/src/winter/fetch/fetch.ts +59 -0
  158. package/example/node_modules/expo/src/winter/fetch/fetch.types.ts +17 -0
  159. package/example/node_modules/expo/src/winter/fetch/fetch.web.ts +1 -0
  160. package/example/node_modules/expo/src/winter/fetch/index.ts +2 -0
  161. package/example/node_modules/expo/src/winter/index.ts +1 -0
  162. package/example/node_modules/expo/src/winter/runtime.native.ts +41 -0
  163. package/example/node_modules/expo/src/winter/runtime.ts +5 -0
  164. package/example/node_modules/expo/src/winter/url.ts +116 -0
  165. package/example/node_modules/expo/types/global.d.ts +38 -0
  166. package/example/node_modules/expo/types/index.d.ts +3 -0
  167. package/example/node_modules/expo/types/metro-require.d.ts +52 -0
  168. package/example/node_modules/expo/types/react-native-web.d.ts +291 -0
  169. package/example/node_modules/expo-modules-autolinking/build/ExpoModuleConfig.d.ts +85 -0
  170. package/example/node_modules/expo-modules-autolinking/build/autolinking/findModules.d.ts +5 -0
  171. package/example/node_modules/expo-modules-autolinking/build/autolinking/generatePackageList.d.ts +11 -0
  172. package/example/node_modules/expo-modules-autolinking/build/autolinking/getConfiguration.d.ts +2 -0
  173. package/example/node_modules/expo-modules-autolinking/build/autolinking/index.d.ts +17 -0
  174. package/example/node_modules/expo-modules-autolinking/build/autolinking/mergeLinkingOptions.d.ts +21 -0
  175. package/example/node_modules/expo-modules-autolinking/build/autolinking/resolveModules.d.ts +9 -0
  176. package/example/node_modules/expo-modules-autolinking/build/autolinking/utils.d.ts +6 -0
  177. package/example/node_modules/expo-modules-autolinking/build/autolinking/verifySearchResults.d.ts +5 -0
  178. package/example/node_modules/expo-modules-autolinking/build/fileUtils.d.ts +18 -0
  179. package/example/node_modules/expo-modules-autolinking/build/index.d.ts +1 -0
  180. package/example/node_modules/expo-modules-autolinking/build/platforms/android.d.ts +38 -0
  181. package/example/node_modules/expo-modules-autolinking/build/platforms/apple.d.ts +15 -0
  182. package/example/node_modules/expo-modules-autolinking/build/platforms/devtools.d.ts +3 -0
  183. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/androidResolver.d.ts +20 -0
  184. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/config.d.ts +5 -0
  185. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/index.d.ts +2 -0
  186. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/iosResolver.d.ts +2 -0
  187. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.d.ts +13 -0
  188. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.types.d.ts +95 -0
  189. package/example/node_modules/expo-modules-autolinking/build/types.d.ts +319 -0
  190. package/example/node_modules/expo-modules-autolinking/e2e/TestUtils.ts +53 -0
  191. package/example/node_modules/expo-modules-autolinking/exports.d.ts +1 -0
  192. package/example/node_modules/expo-modules-autolinking/src/ExpoModuleConfig.ts +181 -0
  193. package/example/node_modules/expo-modules-autolinking/src/autolinking/findModules.ts +259 -0
  194. package/example/node_modules/expo-modules-autolinking/src/autolinking/generatePackageList.ts +46 -0
  195. package/example/node_modules/expo-modules-autolinking/src/autolinking/getConfiguration.ts +7 -0
  196. package/example/node_modules/expo-modules-autolinking/src/autolinking/index.ts +45 -0
  197. package/example/node_modules/expo-modules-autolinking/src/autolinking/mergeLinkingOptions.ts +127 -0
  198. package/example/node_modules/expo-modules-autolinking/src/autolinking/resolveModules.ts +46 -0
  199. package/example/node_modules/expo-modules-autolinking/src/autolinking/utils.ts +37 -0
  200. package/example/node_modules/expo-modules-autolinking/src/autolinking/verifySearchResults.ts +33 -0
  201. package/example/node_modules/expo-modules-autolinking/src/fileUtils.ts +64 -0
  202. package/example/node_modules/expo-modules-autolinking/src/index.ts +262 -0
  203. package/example/node_modules/expo-modules-autolinking/src/platforms/android.ts +303 -0
  204. package/example/node_modules/expo-modules-autolinking/src/platforms/apple.ts +292 -0
  205. package/example/node_modules/expo-modules-autolinking/src/platforms/devtools.ts +25 -0
  206. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts +264 -0
  207. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/config.ts +67 -0
  208. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/index.ts +2 -0
  209. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/iosResolver.ts +37 -0
  210. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.ts +245 -0
  211. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.types.ts +107 -0
  212. package/example/node_modules/expo-modules-autolinking/src/types.ts +384 -0
  213. package/example/node_modules/find-up/index.d.ts +138 -0
  214. package/example/node_modules/glob/dist/commonjs/glob.d.ts +388 -0
  215. package/example/node_modules/glob/dist/commonjs/has-magic.d.ts +14 -0
  216. package/example/node_modules/glob/dist/commonjs/ignore.d.ts +24 -0
  217. package/example/node_modules/glob/dist/commonjs/index.d.ts +97 -0
  218. package/example/node_modules/glob/dist/commonjs/pattern.d.ts +76 -0
  219. package/example/node_modules/glob/dist/commonjs/processor.d.ts +59 -0
  220. package/example/node_modules/glob/dist/commonjs/walker.d.ts +97 -0
  221. package/example/node_modules/glob/dist/esm/glob.d.ts +388 -0
  222. package/example/node_modules/glob/dist/esm/has-magic.d.ts +14 -0
  223. package/example/node_modules/glob/dist/esm/ignore.d.ts +24 -0
  224. package/example/node_modules/glob/dist/esm/index.d.ts +97 -0
  225. package/example/node_modules/glob/dist/esm/pattern.d.ts +76 -0
  226. package/example/node_modules/glob/dist/esm/processor.d.ts +59 -0
  227. package/example/node_modules/glob/dist/esm/walker.d.ts +97 -0
  228. package/example/node_modules/locate-path/index.d.ts +83 -0
  229. package/example/node_modules/log-symbols/node_modules/chalk/types/index.d.ts +97 -0
  230. package/example/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
  231. package/example/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
  232. package/example/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
  233. package/example/node_modules/minimatch/dist/commonjs/escape.d.ts +12 -0
  234. package/example/node_modules/minimatch/dist/commonjs/index.d.ts +94 -0
  235. package/example/node_modules/minimatch/dist/commonjs/unescape.d.ts +17 -0
  236. package/example/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
  237. package/example/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
  238. package/example/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
  239. package/example/node_modules/minimatch/dist/esm/escape.d.ts +12 -0
  240. package/example/node_modules/minimatch/dist/esm/index.d.ts +94 -0
  241. package/example/node_modules/minimatch/dist/esm/unescape.d.ts +17 -0
  242. package/example/node_modules/ora/index.d.ts +257 -0
  243. package/example/node_modules/ora/node_modules/chalk/types/index.d.ts +97 -0
  244. package/example/node_modules/ora/node_modules/strip-ansi/index.d.ts +15 -0
  245. package/example/node_modules/p-locate/index.d.ts +53 -0
  246. package/example/node_modules/path-exists/index.d.ts +28 -0
  247. package/example/package.json +29 -0
  248. package/example/src/constants/styles.ts +43 -0
  249. package/example/src/hooks/useComponentHeight.ts +13 -0
  250. package/example/src/scenes/app.tsx +33 -0
  251. package/example/src/scenes/booleanPicker.tsx +60 -0
  252. package/example/src/scenes/customTypePicker.tsx +83 -0
  253. package/example/src/scenes/numberPicker.tsx +75 -0
  254. package/example/src/scenes/stringPicker.tsx +64 -0
  255. package/lib/module/index.js +6 -6
  256. package/lib/module/index.js.map +1 -1
  257. package/package.json +168 -177
  258. package/src/index.tsx +0 -507
@@ -0,0 +1,235 @@
1
+ /**
2
+ * A message frame packer that serializes a messageKey and a payload into either a JSON string
3
+ * (fast path) or a binary format (for complex payloads).
4
+ *
5
+ * Fast Path (JSON.stringify/JSON.parse):
6
+ * - For simple payloads (e.g., strings, numbers, null, undefined, or plain objects), the packer
7
+ * uses `JSON.stringify` for serialization and `JSON.parse` for deserialization, ensuring
8
+ * optimal performance.
9
+ *
10
+ * Binary Format:
11
+ * - For more complex payloads (e.g., Uint8Array, ArrayBuffer, Blob), the packer uses a binary
12
+ * format with the following structure:
13
+ *
14
+ * +------------------+-------------------+----------------------------+--------------------------+
15
+ * | 4 bytes (Uint32) | Variable length | 1 byte (Uint8) | Variable length |
16
+ * | MessageKeyLength | MessageKey (JSON) | PayloadTypeIndicator (enum)| Payload (binary data) |
17
+ * +------------------+-------------------+----------------------------+--------------------------+
18
+ *
19
+ * 1. MessageKeyLength (4 bytes):
20
+ * - A 4-byte unsigned integer indicating the length of the MessageKey JSON string.
21
+ *
22
+ * 2. MessageKey (Variable length):
23
+ * - The JSON string representing the message key, encoded as UTF-8.
24
+ *
25
+ * 3. PayloadTypeIndicator (1 byte):
26
+ * - A single byte enum value representing the type of the payload (e.g., Uint8Array, String,
27
+ * Object, ArrayBuffer, Blob).
28
+ *
29
+ * 4. Payload (Variable length):
30
+ * - The actual payload data, which can vary in type and length depending on the PayloadType.
31
+ */
32
+
33
+ import { blobToArrayBufferAsync } from '../utils/blobUtils';
34
+
35
+ type MessageKeyTypeBase = string | object;
36
+ type PayloadType = Uint8Array | string | number | null | undefined | object | ArrayBuffer | Blob;
37
+
38
+ enum PayloadTypeIndicator {
39
+ Uint8Array = 1,
40
+ String = 2,
41
+ Number = 3,
42
+ Null = 4,
43
+ Undefined = 5,
44
+ Object = 6,
45
+ ArrayBuffer = 7,
46
+ Blob = 8,
47
+ }
48
+
49
+ interface MessageFrame<T extends MessageKeyTypeBase> {
50
+ messageKey: T;
51
+ payload?: PayloadType;
52
+ }
53
+
54
+ export class MessageFramePacker<T extends MessageKeyTypeBase> {
55
+ private textEncoder = new TextEncoder();
56
+ private textDecoder = new TextDecoder();
57
+
58
+ public pack({ messageKey, payload }: MessageFrame<T>): string | Uint8Array | Promise<Uint8Array> {
59
+ // Fast path to pack as string given `JSON.stringify` is fast.
60
+ if (this.isFastPathPayload(payload)) {
61
+ return JSON.stringify({ messageKey, payload });
62
+ }
63
+
64
+ // Slowest path for Blob returns a promise.
65
+ if (payload instanceof Blob) {
66
+ return new Promise(async (resolve, reject) => {
67
+ try {
68
+ const arrayBuffer = await blobToArrayBufferAsync(payload);
69
+ resolve(
70
+ this.packImpl(
71
+ { messageKey, payload: new Uint8Array(arrayBuffer) },
72
+ PayloadTypeIndicator.Blob
73
+ )
74
+ );
75
+ } catch (error) {
76
+ reject(error);
77
+ }
78
+ });
79
+ }
80
+
81
+ // Slow path for other types returns a Uint8Array.
82
+ return this.packImpl({ messageKey, payload }, undefined);
83
+ }
84
+
85
+ public unpack(packedData: string | ArrayBuffer): MessageFrame<T> {
86
+ // Fast path to unpack as string given `JSON.parse` is fast.
87
+ if (typeof packedData === 'string') {
88
+ return JSON.parse(packedData);
89
+ }
90
+
91
+ // [0] messageKeyLength (4 bytes)
92
+ const messageKeyLengthView = new DataView(packedData, 0, 4);
93
+ const messageKeyLength = messageKeyLengthView.getUint32(0, false);
94
+
95
+ // [1] messageKey (variable length)
96
+ const messageKeyBytes = packedData.slice(4, 4 + messageKeyLength);
97
+ const messageKeyString = this.textDecoder.decode(messageKeyBytes);
98
+ const messageKey = JSON.parse(messageKeyString);
99
+
100
+ // [2] payloadTypeIndicator (1 byte)
101
+ const payloadTypeView = new DataView(packedData, 4 + messageKeyLength, 1);
102
+ const payloadType = payloadTypeView.getUint8(0);
103
+
104
+ // [3] payload (variable length)
105
+ const payloadBinary = packedData.slice(4 + messageKeyLength + 1);
106
+ const payload = this.deserializePayload(payloadBinary, payloadType);
107
+
108
+ return { messageKey, payload };
109
+ }
110
+
111
+ private isFastPathPayload(payload: PayloadType): boolean {
112
+ if (payload == null) {
113
+ return true;
114
+ }
115
+ const payloadType = typeof payload;
116
+ if (payloadType === 'string' || payloadType === 'number') {
117
+ return true;
118
+ }
119
+ if (payloadType === 'object' && payload.constructor === Object) {
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+
125
+ private payloadToUint8Array(payload: PayloadType): Uint8Array {
126
+ if (payload instanceof Uint8Array) {
127
+ return payload;
128
+ } else if (typeof payload === 'string') {
129
+ return this.textEncoder.encode(payload);
130
+ } else if (typeof payload === 'number') {
131
+ const buffer = new ArrayBuffer(8);
132
+ const view = new DataView(buffer);
133
+ view.setFloat64(0, payload, false);
134
+ return new Uint8Array(buffer);
135
+ } else if (payload === null) {
136
+ return new Uint8Array(0);
137
+ } else if (payload === undefined) {
138
+ return new Uint8Array(0);
139
+ } else if (payload instanceof ArrayBuffer) {
140
+ return new Uint8Array(payload);
141
+ } else if (payload instanceof Blob) {
142
+ throw new Error('Blob is not supported in this callsite.');
143
+ } else {
144
+ return this.textEncoder.encode(JSON.stringify(payload));
145
+ }
146
+ }
147
+
148
+ private packImpl(
149
+ { messageKey, payload }: MessageFrame<T>,
150
+ payloadType: PayloadTypeIndicator | undefined
151
+ ): Promise<Uint8Array> | Uint8Array {
152
+ const messageKeyString = JSON.stringify(messageKey);
153
+ const messageKeyBytes = this.textEncoder.encode(messageKeyString);
154
+ const messageKeyLength = messageKeyBytes.length;
155
+ const payloadBinary = this.payloadToUint8Array(payload);
156
+
157
+ const totalLength = 4 + messageKeyLength + 1 + payloadBinary.byteLength;
158
+ const buffer = new ArrayBuffer(totalLength);
159
+ const packedArray = new Uint8Array(buffer);
160
+
161
+ // [0] messageKeyLength (4 bytes)
162
+ const messageKeyLengthView = new DataView(buffer, 0, 4);
163
+ messageKeyLengthView.setUint32(0, messageKeyLength, false);
164
+
165
+ // [1] messageKey (variable length)
166
+ packedArray.set(messageKeyBytes, 4);
167
+
168
+ // [2] payloadTypeIndicator (1 byte)
169
+ const payloadTypeView = new DataView(buffer, 4 + messageKeyLength, 1);
170
+ payloadTypeView.setUint8(0, payloadType ?? MessageFramePacker.getPayloadTypeIndicator(payload));
171
+
172
+ // [3] payload (variable length)
173
+ packedArray.set(payloadBinary, 4 + messageKeyLength + 1);
174
+
175
+ return packedArray;
176
+ }
177
+
178
+ private deserializePayload(
179
+ payloadBinary: ArrayBuffer,
180
+ payloadTypeIndicator: PayloadTypeIndicator
181
+ ): PayloadType {
182
+ switch (payloadTypeIndicator) {
183
+ case PayloadTypeIndicator.Uint8Array: {
184
+ return new Uint8Array(payloadBinary);
185
+ }
186
+ case PayloadTypeIndicator.String: {
187
+ return this.textDecoder.decode(payloadBinary);
188
+ }
189
+ case PayloadTypeIndicator.Number: {
190
+ const view = new DataView(payloadBinary);
191
+ return view.getFloat64(0, false);
192
+ }
193
+ case PayloadTypeIndicator.Null: {
194
+ return null;
195
+ }
196
+ case PayloadTypeIndicator.Undefined: {
197
+ return undefined;
198
+ }
199
+ case PayloadTypeIndicator.Object: {
200
+ const jsonString = this.textDecoder.decode(payloadBinary);
201
+ return JSON.parse(jsonString);
202
+ }
203
+ case PayloadTypeIndicator.ArrayBuffer: {
204
+ return payloadBinary;
205
+ }
206
+ case PayloadTypeIndicator.Blob: {
207
+ return new Blob([payloadBinary]);
208
+ }
209
+ default:
210
+ throw new Error('Unsupported payload type');
211
+ }
212
+ }
213
+
214
+ private static getPayloadTypeIndicator(payload: PayloadType): PayloadTypeIndicator {
215
+ if (payload instanceof Uint8Array) {
216
+ return PayloadTypeIndicator.Uint8Array;
217
+ } else if (typeof payload === 'string') {
218
+ return PayloadTypeIndicator.String;
219
+ } else if (typeof payload === 'number') {
220
+ return PayloadTypeIndicator.Number;
221
+ } else if (payload === null) {
222
+ return PayloadTypeIndicator.Null;
223
+ } else if (payload === undefined) {
224
+ return PayloadTypeIndicator.Undefined;
225
+ } else if (payload instanceof ArrayBuffer) {
226
+ return PayloadTypeIndicator.ArrayBuffer;
227
+ } else if (payload instanceof Blob) {
228
+ return PayloadTypeIndicator.Blob;
229
+ } else if (typeof payload === 'object') {
230
+ return PayloadTypeIndicator.Object;
231
+ } else {
232
+ throw new Error('Unsupported payload type');
233
+ }
234
+ }
235
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A transport protocol version between the app and the webui.
3
+ * It shows a warning in handshaking stage if the version is different between the app and the webui.
4
+ * The value should be increased when the protocol is changed.
5
+ */
6
+ export const PROTOCOL_VERSION = 1;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The backing store for the WebSocket connection and reference count.
3
+ * This is used for connection multiplexing.
4
+ */
5
+ export class WebSocketBackingStore {
6
+ constructor(
7
+ public ws: WebSocket | null = null,
8
+ public refCount: number = 0
9
+ ) {}
10
+ }
@@ -0,0 +1,318 @@
1
+ import type { DevToolsPluginClientOptions } from './devtools.types';
2
+
3
+ export interface Options {
4
+ /**
5
+ * Reconnect interval in milliseconds.
6
+ * @default 1500
7
+ */
8
+ retriesInterval?: number;
9
+
10
+ /**
11
+ * The maximum number of retries.
12
+ * @default 200
13
+ */
14
+ maxRetries?: number;
15
+
16
+ /**
17
+ * The timeout in milliseconds for the WebSocket connecting.
18
+ */
19
+ connectTimeout?: number;
20
+
21
+ /**
22
+ * The error handler.
23
+ * @default throwing an error
24
+ */
25
+ onError?: (error: Error) => void;
26
+
27
+ /**
28
+ * The callback to be called when the WebSocket is reconnected.
29
+ * @default no-op
30
+ */
31
+ onReconnect?: (reason: string) => void;
32
+
33
+ /**
34
+ * The [`binaryType`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType).
35
+ */
36
+ binaryType?: DevToolsPluginClientOptions['websocketBinaryType'];
37
+ }
38
+
39
+ interface InternalEventListeners {
40
+ message?: Set<(event: WebSocketMessageEvent) => void>;
41
+ open?: Set<() => void>;
42
+ error?: Set<(event: WebSocketErrorEvent) => void>;
43
+ close?: Set<(event: WebSocketCloseEvent) => void>;
44
+ [eventName: string]: undefined | Set<(event: any) => void>;
45
+ }
46
+
47
+ export class WebSocketWithReconnect implements WebSocket {
48
+ private readonly retriesInterval: number;
49
+ private readonly maxRetries: number;
50
+ private readonly connectTimeout: number;
51
+ private readonly onError: (error: Error) => void;
52
+ private readonly onReconnect: (reason: string) => void;
53
+
54
+ private ws: WebSocket | null = null;
55
+ private retries = 0;
56
+ private connectTimeoutHandle: ReturnType<typeof setTimeout> | null = null;
57
+ private isClosed = false;
58
+ private sendQueue: (string | ArrayBufferView | Blob | ArrayBufferLike)[] = [];
59
+ private lastCloseEvent: { code?: number; reason?: string; message?: string } | null = null;
60
+ private eventListeners: InternalEventListeners;
61
+
62
+ private readonly wsBinaryType?: Options['binaryType'];
63
+
64
+ constructor(
65
+ public readonly url: string,
66
+ options?: Options
67
+ ) {
68
+ this.retriesInterval = options?.retriesInterval ?? 1500;
69
+ this.maxRetries = options?.maxRetries ?? 200;
70
+ this.connectTimeout = options?.connectTimeout ?? 5000;
71
+ this.onError =
72
+ options?.onError ??
73
+ ((error) => {
74
+ throw error;
75
+ });
76
+ this.onReconnect = options?.onReconnect ?? (() => {});
77
+ this.wsBinaryType = options?.binaryType;
78
+ this.eventListeners = Object.create(null);
79
+
80
+ this.connect();
81
+ }
82
+
83
+ public close(code?: number, reason?: string) {
84
+ this.clearConnectTimeoutIfNeeded();
85
+ this.emitEvent(
86
+ 'close',
87
+ (this.lastCloseEvent ?? {
88
+ code: code ?? 1000,
89
+ reason: reason ?? 'Explicit closing',
90
+ message: 'Explicit closing',
91
+ }) as WebSocketCloseEvent
92
+ );
93
+ this.lastCloseEvent = null;
94
+ this.isClosed = true;
95
+ this.eventListeners = Object.create(null);
96
+ this.sendQueue = [];
97
+ if (this.ws != null) {
98
+ const ws = this.ws;
99
+ this.ws = null;
100
+ this.wsClose(ws);
101
+ }
102
+ }
103
+
104
+ public addEventListener(event: 'message', listener: (event: WebSocketMessageEvent) => void): void;
105
+ public addEventListener(event: 'open', listener: () => void): void;
106
+ public addEventListener(event: 'error', listener: (event: WebSocketErrorEvent) => void): void;
107
+ public addEventListener(event: 'close', listener: (event: WebSocketCloseEvent) => void): void;
108
+ public addEventListener(event: string, listener: (event: any) => void) {
109
+ const listeners = this.eventListeners[event] || (this.eventListeners[event] = new Set());
110
+ listeners.add(listener);
111
+ }
112
+
113
+ public removeEventListener(event: string, listener: (event: any) => void) {
114
+ this.eventListeners[event]?.delete(listener);
115
+ }
116
+
117
+ //#region Internals
118
+
119
+ private connect() {
120
+ if (this.ws != null) {
121
+ return;
122
+ }
123
+ this.connectTimeoutHandle = setTimeout(this.handleConnectTimeout, this.connectTimeout);
124
+
125
+ this.ws = new WebSocket(this.url.toString());
126
+ if (this.wsBinaryType != null) {
127
+ this.ws.binaryType = this.wsBinaryType;
128
+ }
129
+ this.ws.addEventListener('message', this.handleMessage);
130
+ this.ws.addEventListener('open', this.handleOpen);
131
+ // @ts-ignore TypeScript expects (e: Event) => any, but we want (e: WebSocketErrorEvent) => any
132
+ this.ws.addEventListener('error', this.handleError);
133
+ this.ws.addEventListener('close', this.handleClose);
134
+ }
135
+
136
+ public send(data: string | ArrayBufferView | Blob | ArrayBufferLike): void {
137
+ if (this.isClosed) {
138
+ this.onError(new Error('Unable to send data: WebSocket is closed'));
139
+ return;
140
+ }
141
+
142
+ if (this.retries >= this.maxRetries) {
143
+ this.onError(
144
+ new Error(`Unable to send data: Exceeded max retries - retries[${this.retries}]`)
145
+ );
146
+ return;
147
+ }
148
+
149
+ const ws = this.ws;
150
+ if (ws != null && ws.readyState === WebSocket.OPEN) {
151
+ ws.send(data);
152
+ } else {
153
+ this.sendQueue.push(data);
154
+ }
155
+ }
156
+
157
+ private emitEvent(event: 'message', payload: WebSocketMessageEvent): void;
158
+ private emitEvent(event: 'open', payload?: void): void;
159
+ private emitEvent(event: 'error', payload: WebSocketErrorEvent): void;
160
+ private emitEvent(event: 'close', payload: WebSocketCloseEvent): void;
161
+ private emitEvent(event: string, payload: any) {
162
+ const listeners = this.eventListeners[event];
163
+ if (listeners) {
164
+ for (const listener of listeners) {
165
+ listener(payload);
166
+ }
167
+ }
168
+ }
169
+
170
+ private handleOpen = () => {
171
+ this.clearConnectTimeoutIfNeeded();
172
+ this.lastCloseEvent = null;
173
+ this.emitEvent('open');
174
+
175
+ const sendQueue = this.sendQueue;
176
+ this.sendQueue = [];
177
+ for (const data of sendQueue) {
178
+ this.send(data);
179
+ }
180
+ };
181
+
182
+ private handleMessage = (event: WebSocketMessageEvent) => {
183
+ this.emitEvent('message', event);
184
+ };
185
+
186
+ private handleError = (event: WebSocketErrorEvent) => {
187
+ this.clearConnectTimeoutIfNeeded();
188
+ this.emitEvent('error', event);
189
+ this.reconnectIfNeeded(`WebSocket error - ${event.message}`);
190
+ };
191
+
192
+ private handleClose = (event: WebSocketCloseEvent) => {
193
+ this.clearConnectTimeoutIfNeeded();
194
+ this.lastCloseEvent = {
195
+ code: event.code,
196
+ reason: event.reason,
197
+ message: event.message,
198
+ };
199
+ this.reconnectIfNeeded(`WebSocket closed - code[${event.code}] reason[${event.reason}]`);
200
+ };
201
+
202
+ private handleConnectTimeout = () => {
203
+ this.reconnectIfNeeded('Timeout from connecting to the WebSocket');
204
+ };
205
+
206
+ private clearConnectTimeoutIfNeeded() {
207
+ if (this.connectTimeoutHandle != null) {
208
+ clearTimeout(this.connectTimeoutHandle);
209
+ this.connectTimeoutHandle = null;
210
+ }
211
+ }
212
+
213
+ private reconnectIfNeeded(reason: string) {
214
+ if (this.ws != null) {
215
+ this.wsClose(this.ws);
216
+ this.ws = null;
217
+ }
218
+ if (this.isClosed) {
219
+ return;
220
+ }
221
+
222
+ if (this.retries >= this.maxRetries) {
223
+ this.onError(new Error('Exceeded max retries'));
224
+ this.close();
225
+ return;
226
+ }
227
+
228
+ setTimeout(() => {
229
+ this.retries += 1;
230
+ this.connect();
231
+ this.onReconnect(reason);
232
+ }, this.retriesInterval);
233
+ }
234
+
235
+ private wsClose(ws: WebSocket) {
236
+ try {
237
+ ws.removeEventListener('message', this.handleMessage);
238
+ ws.removeEventListener('open', this.handleOpen);
239
+ ws.removeEventListener('close', this.handleClose);
240
+
241
+ // WebSocket throws errors if we don't handle the error event.
242
+ // Specifically when closing a ws in CONNECTING readyState,
243
+ // WebSocket will have `WebSocket was closed before the connection was established` error.
244
+ // We won't like to have the exception, so set a noop error handler.
245
+ ws.onerror = () => {};
246
+
247
+ ws.close();
248
+ } catch {}
249
+ }
250
+
251
+ public get readyState() {
252
+ // Only return closed if the WebSocket is explicitly closed or exceeds max retries.
253
+ if (this.isClosed) {
254
+ return WebSocket.CLOSED;
255
+ }
256
+
257
+ const readyState = this.ws?.readyState;
258
+ if (readyState === WebSocket.CLOSED) {
259
+ return WebSocket.CONNECTING;
260
+ }
261
+ return readyState ?? WebSocket.CONNECTING;
262
+ }
263
+
264
+ //#endregion
265
+
266
+ //#region WebSocket API proxy
267
+
268
+ public readonly CONNECTING = 0;
269
+ public readonly OPEN = 1;
270
+ public readonly CLOSING = 2;
271
+ public readonly CLOSED = 3;
272
+
273
+ public get binaryType() {
274
+ return this.ws?.binaryType ?? 'blob';
275
+ }
276
+
277
+ public get bufferedAmount() {
278
+ return this.ws?.bufferedAmount ?? 0;
279
+ }
280
+
281
+ public get extensions() {
282
+ return this.ws?.extensions ?? '';
283
+ }
284
+
285
+ public get protocol() {
286
+ return this.ws?.protocol ?? '';
287
+ }
288
+
289
+ public ping(): void {
290
+ return this.ws?.ping();
291
+ }
292
+
293
+ public dispatchEvent(event: Event) {
294
+ return this.ws?.dispatchEvent(event) ?? false;
295
+ }
296
+
297
+ //#endregion
298
+
299
+ //#regions Unsupported legacy properties
300
+
301
+ public set onclose(_value: ((e: WebSocketCloseEvent) => any) | null) {
302
+ throw new Error('Unsupported legacy property, use addEventListener instead');
303
+ }
304
+
305
+ public set onerror(_value: ((e: Event) => any) | null) {
306
+ throw new Error('Unsupported legacy property, use addEventListener instead');
307
+ }
308
+
309
+ public set onmessage(_value: ((e: WebSocketMessageEvent) => any) | null) {
310
+ throw new Error('Unsupported legacy property, use addEventListener instead');
311
+ }
312
+
313
+ public set onopen(_value: (() => any) | null) {
314
+ throw new Error('Unsupported legacy property, use addEventListener instead');
315
+ }
316
+
317
+ //#endregion
318
+ }
@@ -0,0 +1,50 @@
1
+ import type { WebSocketBackingStore } from './WebSocketBackingStore';
2
+
3
+ /**
4
+ * The connection info for devtools plugins client.
5
+ */
6
+ export interface ConnectionInfo {
7
+ /** Indicates the sender towards the devtools plugin. */
8
+ sender:
9
+ | 'app' // client running in the app environment.
10
+ | 'browser'; // client running in the browser environment.
11
+
12
+ /** Dev server address. */
13
+ devServer: string;
14
+
15
+ /** The plugin name. */
16
+ pluginName: string;
17
+
18
+ /**
19
+ * The backing store for the WebSocket connection. Exposed for testing.
20
+ * If not provided, the default singleton instance will be used.
21
+ * @hidden
22
+ */
23
+ wsStore?: WebSocketBackingStore;
24
+
25
+ /**
26
+ * The transport protocol version between the app and the webui.
27
+ */
28
+ protocolVersion: number;
29
+ }
30
+
31
+ /**
32
+ * Options for the devtools plugin client.
33
+ */
34
+ export interface DevToolsPluginClientOptions {
35
+ /**
36
+ * The underlying WebSocket [`binaryType`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType).
37
+ */
38
+ websocketBinaryType?: 'arraybuffer' | 'blob';
39
+ }
40
+
41
+ /**
42
+ * The handshake messages for the devtools plugin client.
43
+ * @hidden
44
+ */
45
+ export interface HandshakeMessageParams {
46
+ protocolVersion: number;
47
+ pluginName: string;
48
+ method: 'handshake' | 'terminateBrowserClient';
49
+ browserClientId: string;
50
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Get the dev server address.
3
+ */
4
+
5
+ import { PROTOCOL_VERSION } from './ProtocolVersion';
6
+ import type { ConnectionInfo } from './devtools.types';
7
+
8
+ export function getConnectionInfo(): Omit<ConnectionInfo, 'pluginName'> {
9
+ const getDevServer = require('react-native/Libraries/Core/Devtools/getDevServer').default;
10
+ const devServer = getDevServer()
11
+ .url.replace(/^https?:\/\//, '')
12
+ .replace(/\/?$/, '') as string;
13
+ return {
14
+ protocolVersion: PROTOCOL_VERSION,
15
+ sender: 'app',
16
+ devServer,
17
+ };
18
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Get the dev server address.
3
+ */
4
+
5
+ import { PROTOCOL_VERSION } from './ProtocolVersion';
6
+ import type { ConnectionInfo } from './devtools.types';
7
+
8
+ export function getConnectionInfo(): Omit<ConnectionInfo, 'pluginName'> {
9
+ const devServerQuery = new URLSearchParams(window.location.search).get('devServer');
10
+ const host = window.location.origin.replace(/^https?:\/\//, '');
11
+ return {
12
+ protocolVersion: PROTOCOL_VERSION,
13
+ sender: 'browser',
14
+ devServer: devServerQuery || host,
15
+ };
16
+ }