@amabeth/repeating-wheel-picker 1.1.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.
- package/LICENSE +20 -20
- package/README.md +57 -57
- package/example/index.ts +8 -0
- package/example/node_modules/@expo/cli/static/template/+html.tsx +28 -0
- package/example/node_modules/@expo/cli/static/template/+native-intent.ts +9 -0
- package/example/node_modules/@expo/cli/static/template/[...rsc]+api.ts +16 -0
- package/example/node_modules/ansi-styles/index.d.ts +345 -0
- package/example/node_modules/chalk/index.d.ts +415 -0
- package/example/node_modules/commander/typings/index.d.ts +627 -0
- package/example/node_modules/expo/Expo.podspec +108 -0
- package/example/node_modules/expo/build/Expo.d.ts +8 -0
- package/example/node_modules/expo/build/Expo.fx.d.ts +4 -0
- package/example/node_modules/expo/build/Expo.fx.web.d.ts +3 -0
- package/example/node_modules/expo/build/devtools/DevToolsPluginClient.d.ts +72 -0
- package/example/node_modules/expo/build/devtools/DevToolsPluginClientFactory.d.ts +16 -0
- package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplApp.d.ts +15 -0
- package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplBrowser.d.ts +14 -0
- package/example/node_modules/expo/build/devtools/MessageFramePacker.d.ts +50 -0
- package/example/node_modules/expo/build/devtools/ProtocolVersion.d.ts +7 -0
- package/example/node_modules/expo/build/devtools/WebSocketBackingStore.d.ts +10 -0
- package/example/node_modules/expo/build/devtools/WebSocketWithReconnect.d.ts +81 -0
- package/example/node_modules/expo/build/devtools/devtools.types.d.ts +42 -0
- package/example/node_modules/expo/build/devtools/getConnectionInfo.d.ts +6 -0
- package/example/node_modules/expo/build/devtools/getConnectionInfo.native.d.ts +6 -0
- package/example/node_modules/expo/build/devtools/index.d.ts +12 -0
- package/example/node_modules/expo/build/devtools/logger.d.ts +6 -0
- package/example/node_modules/expo/build/dom/base.d.ts +5 -0
- package/example/node_modules/expo/build/dom/dom-entry.d.ts +3 -0
- package/example/node_modules/expo/build/dom/dom-hooks.d.ts +8 -0
- package/example/node_modules/expo/build/dom/dom.d.ts +5 -0
- package/example/node_modules/expo/build/dom/dom.types.d.ts +34 -0
- package/example/node_modules/expo/build/dom/dom.web.d.ts +3 -0
- package/example/node_modules/expo/build/dom/global-events.d.ts +4 -0
- package/example/node_modules/expo/build/dom/injection.d.ts +9 -0
- package/example/node_modules/expo/build/dom/internal.d.ts +3 -0
- package/example/node_modules/expo/build/dom/internal.web.d.ts +2 -0
- package/example/node_modules/expo/build/dom/marshal.d.ts +4 -0
- package/example/node_modules/expo/build/dom/webview/ExpoDOMWebView.d.ts +6 -0
- package/example/node_modules/expo/build/dom/webview/RNWebView.d.ts +7 -0
- package/example/node_modules/expo/build/dom/webview/useDebugZeroHeight.d.ts +12 -0
- package/example/node_modules/expo/build/dom/webview-wrapper.d.ts +16 -0
- package/example/node_modules/expo/build/environment/DevLoadingView.d.ts +3 -0
- package/example/node_modules/expo/build/environment/DevLoadingView.web.d.ts +3 -0
- package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.d.ts +9 -0
- package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.native.d.ts +3 -0
- package/example/node_modules/expo/build/environment/ExpoGo.d.ts +31 -0
- package/example/node_modules/expo/build/environment/ExpoGo.web.d.ts +3 -0
- package/example/node_modules/expo/build/environment/getInitialSafeArea.d.ts +7 -0
- package/example/node_modules/expo/build/environment/getInitialSafeArea.native.d.ts +11 -0
- package/example/node_modules/expo/build/errors/AppEntryNotFound.d.ts +2 -0
- package/example/node_modules/expo/build/errors/ExpoErrorManager.d.ts +8 -0
- package/example/node_modules/expo/build/errors/ExpoErrorManager.native.d.ts +4 -0
- package/example/node_modules/expo/build/hooks/useEvent.d.ts +59 -0
- package/example/node_modules/expo/build/launch/registerRootComponent.d.ts +30 -0
- package/example/node_modules/expo/build/launch/withDevTools.d.ts +3 -0
- package/example/node_modules/expo/build/launch/withDevTools.ios.d.ts +7 -0
- package/example/node_modules/expo/build/launch/withDevTools.web.d.ts +3 -0
- package/example/node_modules/expo/build/timer/polyfillNextTick.d.ts +6 -0
- package/example/node_modules/expo/build/utils/blobUtils.d.ts +9 -0
- package/example/node_modules/expo/build/utils/getBundleUrl.d.ts +2 -0
- package/example/node_modules/expo/build/utils/getBundleUrl.native.d.ts +2 -0
- package/example/node_modules/expo/build/utils/getBundleUrl.web.d.ts +2 -0
- package/example/node_modules/expo/build/winter/FormData.d.ts +49 -0
- package/example/node_modules/expo/build/winter/ImportMetaRegistry.d.ts +9 -0
- package/example/node_modules/expo/build/winter/TextDecoder.d.ts +20 -0
- package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.d.ts +2 -0
- package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.web.d.ts +10 -0
- package/example/node_modules/expo/build/winter/fetch/FetchErrors.d.ts +8 -0
- package/example/node_modules/expo/build/winter/fetch/FetchResponse.d.ts +31 -0
- package/example/node_modules/expo/build/winter/fetch/NativeRequest.d.ts +30 -0
- package/example/node_modules/expo/build/winter/fetch/RequestUtils.d.ts +21 -0
- package/example/node_modules/expo/build/winter/fetch/convertFormData.d.ts +19 -0
- package/example/node_modules/expo/build/winter/fetch/fetch.d.ts +4 -0
- package/example/node_modules/expo/build/winter/fetch/fetch.types.d.ts +16 -0
- package/example/node_modules/expo/build/winter/fetch/fetch.web.d.ts +2 -0
- package/example/node_modules/expo/build/winter/fetch/index.d.ts +3 -0
- package/example/node_modules/expo/build/winter/index.d.ts +2 -0
- package/example/node_modules/expo/build/winter/runtime.d.ts +2 -0
- package/example/node_modules/expo/build/winter/runtime.native.d.ts +2 -0
- package/example/node_modules/expo/build/winter/url.d.ts +23 -0
- package/example/node_modules/expo/config-plugins.d.ts +1 -0
- package/example/node_modules/expo/config.d.ts +1 -0
- package/example/node_modules/expo/devtools.d.ts +1 -0
- package/example/node_modules/expo/dom/global.d.ts +1 -0
- package/example/node_modules/expo/dom/index.d.ts +1 -0
- package/example/node_modules/expo/dom/internal.d.ts +1 -0
- package/example/node_modules/expo/fetch.d.ts +1 -0
- package/example/node_modules/expo/fingerprint.d.ts +1 -0
- package/example/node_modules/expo/metro-config.d.ts +1 -0
- package/example/node_modules/expo/react-native.config.js +50 -0
- package/example/node_modules/expo/src/Expo.fx.tsx +53 -0
- package/example/node_modules/expo/src/Expo.fx.web.tsx +21 -0
- package/example/node_modules/expo/src/Expo.ts +30 -0
- package/example/node_modules/expo/src/devtools/DevToolsPluginClient.ts +240 -0
- package/example/node_modules/expo/src/devtools/DevToolsPluginClientFactory.ts +73 -0
- package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplApp.ts +56 -0
- package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplBrowser.ts +38 -0
- package/example/node_modules/expo/src/devtools/MessageFramePacker.ts +235 -0
- package/example/node_modules/expo/src/devtools/ProtocolVersion.ts +6 -0
- package/example/node_modules/expo/src/devtools/WebSocketBackingStore.ts +10 -0
- package/example/node_modules/expo/src/devtools/WebSocketWithReconnect.ts +318 -0
- package/example/node_modules/expo/src/devtools/devtools.types.ts +50 -0
- package/example/node_modules/expo/src/devtools/getConnectionInfo.native.ts +18 -0
- package/example/node_modules/expo/src/devtools/getConnectionInfo.ts +16 -0
- package/example/node_modules/expo/src/devtools/index.ts +53 -0
- package/example/node_modules/expo/src/devtools/logger.ts +29 -0
- package/example/node_modules/expo/src/dom/base.ts +62 -0
- package/example/node_modules/expo/src/dom/dom-entry.tsx +128 -0
- package/example/node_modules/expo/src/dom/dom-hooks.ts +46 -0
- package/example/node_modules/expo/src/dom/dom.ts +8 -0
- package/example/node_modules/expo/src/dom/dom.types.ts +39 -0
- package/example/node_modules/expo/src/dom/dom.web.ts +6 -0
- package/example/node_modules/expo/src/dom/global-events.ts +16 -0
- package/example/node_modules/expo/src/dom/injection.ts +42 -0
- package/example/node_modules/expo/src/dom/internal.ts +5 -0
- package/example/node_modules/expo/src/dom/internal.web.ts +1 -0
- package/example/node_modules/expo/src/dom/marshal.tsx +116 -0
- package/example/node_modules/expo/src/dom/webview/ExpoDOMWebView.ts +10 -0
- package/example/node_modules/expo/src/dom/webview/RNWebView.ts +12 -0
- package/example/node_modules/expo/src/dom/webview/useDebugZeroHeight.ts +62 -0
- package/example/node_modules/expo/src/dom/webview-wrapper.tsx +253 -0
- package/example/node_modules/expo/src/environment/DevLoadingView.tsx +123 -0
- package/example/node_modules/expo/src/environment/DevLoadingView.web.tsx +135 -0
- package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.native.ts +3 -0
- package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.ts +7 -0
- package/example/node_modules/expo/src/environment/ExpoGo.ts +53 -0
- package/example/node_modules/expo/src/environment/ExpoGo.web.ts +7 -0
- package/example/node_modules/expo/src/environment/getInitialSafeArea.native.ts +16 -0
- package/example/node_modules/expo/src/environment/getInitialSafeArea.ts +8 -0
- package/example/node_modules/expo/src/errors/AppEntryNotFound.tsx +35 -0
- package/example/node_modules/expo/src/errors/ExpoErrorManager.native.ts +51 -0
- package/example/node_modules/expo/src/errors/ExpoErrorManager.ts +11 -0
- package/example/node_modules/expo/src/hooks/useEvent.ts +112 -0
- package/example/node_modules/expo/src/launch/registerRootComponent.tsx +64 -0
- package/example/node_modules/expo/src/launch/withDevTools.ios.tsx +47 -0
- package/example/node_modules/expo/src/launch/withDevTools.tsx +30 -0
- package/example/node_modules/expo/src/launch/withDevTools.web.tsx +23 -0
- package/example/node_modules/expo/src/timer/polyfillNextTick.ts +10 -0
- package/example/node_modules/expo/src/ts-declarations/console.d.ts +47 -0
- package/example/node_modules/expo/src/ts-declarations/global.d.ts +12 -0
- package/example/node_modules/expo/src/ts-declarations/react-native.d.ts +34 -0
- package/example/node_modules/expo/src/ts-declarations/whatwg-url-without-unicode.d.ts +186 -0
- package/example/node_modules/expo/src/utils/blobUtils.ts +23 -0
- package/example/node_modules/expo/src/utils/getBundleUrl.native.ts +17 -0
- package/example/node_modules/expo/src/utils/getBundleUrl.ts +5 -0
- package/example/node_modules/expo/src/utils/getBundleUrl.web.ts +21 -0
- package/example/node_modules/expo/src/winter/FormData.ts +222 -0
- package/example/node_modules/expo/src/winter/ImportMetaRegistry.ts +14 -0
- package/example/node_modules/expo/src/winter/TextDecoder.ts +429 -0
- package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.ts +3 -0
- package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.web.ts +7 -0
- package/example/node_modules/expo/src/winter/fetch/FetchErrors.ts +11 -0
- package/example/node_modules/expo/src/winter/fetch/FetchResponse.ts +146 -0
- package/example/node_modules/expo/src/winter/fetch/NativeRequest.ts +38 -0
- package/example/node_modules/expo/src/winter/fetch/RequestUtils.ts +124 -0
- package/example/node_modules/expo/src/winter/fetch/convertFormData.ts +92 -0
- package/example/node_modules/expo/src/winter/fetch/fetch.ts +59 -0
- package/example/node_modules/expo/src/winter/fetch/fetch.types.ts +17 -0
- package/example/node_modules/expo/src/winter/fetch/fetch.web.ts +1 -0
- package/example/node_modules/expo/src/winter/fetch/index.ts +2 -0
- package/example/node_modules/expo/src/winter/index.ts +1 -0
- package/example/node_modules/expo/src/winter/runtime.native.ts +41 -0
- package/example/node_modules/expo/src/winter/runtime.ts +5 -0
- package/example/node_modules/expo/src/winter/url.ts +116 -0
- package/example/node_modules/expo/types/global.d.ts +38 -0
- package/example/node_modules/expo/types/index.d.ts +3 -0
- package/example/node_modules/expo/types/metro-require.d.ts +52 -0
- package/example/node_modules/expo/types/react-native-web.d.ts +291 -0
- package/example/node_modules/expo-modules-autolinking/build/ExpoModuleConfig.d.ts +85 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/findModules.d.ts +5 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/generatePackageList.d.ts +11 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/getConfiguration.d.ts +2 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/index.d.ts +17 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/mergeLinkingOptions.d.ts +21 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/resolveModules.d.ts +9 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/utils.d.ts +6 -0
- package/example/node_modules/expo-modules-autolinking/build/autolinking/verifySearchResults.d.ts +5 -0
- package/example/node_modules/expo-modules-autolinking/build/fileUtils.d.ts +18 -0
- package/example/node_modules/expo-modules-autolinking/build/index.d.ts +1 -0
- package/example/node_modules/expo-modules-autolinking/build/platforms/android.d.ts +38 -0
- package/example/node_modules/expo-modules-autolinking/build/platforms/apple.d.ts +15 -0
- package/example/node_modules/expo-modules-autolinking/build/platforms/devtools.d.ts +3 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/androidResolver.d.ts +20 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/config.d.ts +5 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/index.d.ts +2 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/iosResolver.d.ts +2 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.d.ts +13 -0
- package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.types.d.ts +95 -0
- package/example/node_modules/expo-modules-autolinking/build/types.d.ts +319 -0
- package/example/node_modules/expo-modules-autolinking/e2e/TestUtils.ts +53 -0
- package/example/node_modules/expo-modules-autolinking/exports.d.ts +1 -0
- package/example/node_modules/expo-modules-autolinking/src/ExpoModuleConfig.ts +181 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/findModules.ts +259 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/generatePackageList.ts +46 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/getConfiguration.ts +7 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/index.ts +45 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/mergeLinkingOptions.ts +127 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/resolveModules.ts +46 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/utils.ts +37 -0
- package/example/node_modules/expo-modules-autolinking/src/autolinking/verifySearchResults.ts +33 -0
- package/example/node_modules/expo-modules-autolinking/src/fileUtils.ts +64 -0
- package/example/node_modules/expo-modules-autolinking/src/index.ts +262 -0
- package/example/node_modules/expo-modules-autolinking/src/platforms/android.ts +303 -0
- package/example/node_modules/expo-modules-autolinking/src/platforms/apple.ts +292 -0
- package/example/node_modules/expo-modules-autolinking/src/platforms/devtools.ts +25 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts +264 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/config.ts +67 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/index.ts +2 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/iosResolver.ts +37 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.ts +245 -0
- package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.types.ts +107 -0
- package/example/node_modules/expo-modules-autolinking/src/types.ts +384 -0
- package/example/node_modules/find-up/index.d.ts +138 -0
- package/example/node_modules/glob/dist/commonjs/glob.d.ts +388 -0
- package/example/node_modules/glob/dist/commonjs/has-magic.d.ts +14 -0
- package/example/node_modules/glob/dist/commonjs/ignore.d.ts +24 -0
- package/example/node_modules/glob/dist/commonjs/index.d.ts +97 -0
- package/example/node_modules/glob/dist/commonjs/pattern.d.ts +76 -0
- package/example/node_modules/glob/dist/commonjs/processor.d.ts +59 -0
- package/example/node_modules/glob/dist/commonjs/walker.d.ts +97 -0
- package/example/node_modules/glob/dist/esm/glob.d.ts +388 -0
- package/example/node_modules/glob/dist/esm/has-magic.d.ts +14 -0
- package/example/node_modules/glob/dist/esm/ignore.d.ts +24 -0
- package/example/node_modules/glob/dist/esm/index.d.ts +97 -0
- package/example/node_modules/glob/dist/esm/pattern.d.ts +76 -0
- package/example/node_modules/glob/dist/esm/processor.d.ts +59 -0
- package/example/node_modules/glob/dist/esm/walker.d.ts +97 -0
- package/example/node_modules/locate-path/index.d.ts +83 -0
- package/example/node_modules/log-symbols/node_modules/chalk/types/index.d.ts +97 -0
- package/example/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
- package/example/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
- package/example/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
- package/example/node_modules/minimatch/dist/commonjs/escape.d.ts +12 -0
- package/example/node_modules/minimatch/dist/commonjs/index.d.ts +94 -0
- package/example/node_modules/minimatch/dist/commonjs/unescape.d.ts +17 -0
- package/example/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
- package/example/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
- package/example/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
- package/example/node_modules/minimatch/dist/esm/escape.d.ts +12 -0
- package/example/node_modules/minimatch/dist/esm/index.d.ts +94 -0
- package/example/node_modules/minimatch/dist/esm/unescape.d.ts +17 -0
- package/example/node_modules/ora/index.d.ts +257 -0
- package/example/node_modules/ora/node_modules/chalk/types/index.d.ts +97 -0
- package/example/node_modules/ora/node_modules/strip-ansi/index.d.ts +15 -0
- package/example/node_modules/p-locate/index.d.ts +53 -0
- package/example/node_modules/path-exists/index.d.ts +28 -0
- package/example/package.json +29 -0
- package/example/src/constants/styles.ts +43 -0
- package/example/src/hooks/useComponentHeight.ts +13 -0
- package/example/src/scenes/app.tsx +33 -0
- package/example/src/scenes/booleanPicker.tsx +60 -0
- package/example/src/scenes/customTypePicker.tsx +83 -0
- package/example/src/scenes/numberPicker.tsx +75 -0
- package/example/src/scenes/stringPicker.tsx +64 -0
- package/lib/module/index.js +6 -6
- package/lib/module/index.js.map +1 -1
- package/package.json +168 -183
- package/src/index.tsx +0 -507
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { ExpoFetchModule } from './ExpoFetchModule';
|
|
2
|
+
import type { NativeResponse } from './NativeRequest';
|
|
3
|
+
|
|
4
|
+
const ConcreteNativeResponse = ExpoFetchModule.NativeResponse as typeof NativeResponse;
|
|
5
|
+
export type AbortSubscriptionCleanupFunction = () => void;
|
|
6
|
+
|
|
7
|
+
// FormData from react-native is not compatible with the web standard.
|
|
8
|
+
// We need to extend it with the react-native FormData.
|
|
9
|
+
type RNFormData = Awaited<ReturnType<globalThis.Response['formData']>>;
|
|
10
|
+
type UniversalFormData = globalThis.FormData & RNFormData;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A response implementation for the `fetch.Response` API.
|
|
14
|
+
*/
|
|
15
|
+
export class FetchResponse extends ConcreteNativeResponse implements Response {
|
|
16
|
+
private streamingState: 'none' | 'started' | 'completed' = 'none';
|
|
17
|
+
private bodyStream: ReadableStream<Uint8Array> | null = null;
|
|
18
|
+
|
|
19
|
+
constructor(private readonly abortCleanupFunction: AbortSubscriptionCleanupFunction) {
|
|
20
|
+
super();
|
|
21
|
+
this.addListener('readyForJSFinalization', this.finalize);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get body(): ReadableStream<Uint8Array> | null {
|
|
25
|
+
if (this.bodyStream == null) {
|
|
26
|
+
const response = this;
|
|
27
|
+
|
|
28
|
+
// This flag prevents enqueuing data after the stream is closed or canceled.
|
|
29
|
+
// Because it might be too late for the multithreaded native code to stop enqueuing data,
|
|
30
|
+
// we cannot simply rely on the native code to stop sending `didReceiveResponseData`.
|
|
31
|
+
let isControllerClosed = false;
|
|
32
|
+
|
|
33
|
+
this.bodyStream = new ReadableStream({
|
|
34
|
+
start(controller) {
|
|
35
|
+
if (response.streamingState === 'completed') {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
response.addListener('didReceiveResponseData', (data: Uint8Array) => {
|
|
39
|
+
if (!isControllerClosed) {
|
|
40
|
+
controller.enqueue(data);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
response.addListener('didComplete', () => {
|
|
45
|
+
controller.close();
|
|
46
|
+
isControllerClosed = true;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
response.addListener('didFailWithError', (error: string) => {
|
|
50
|
+
controller.error(new Error(error));
|
|
51
|
+
isControllerClosed = true;
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
async pull(controller) {
|
|
55
|
+
if (response.streamingState === 'none') {
|
|
56
|
+
const completedData = await response.startStreaming();
|
|
57
|
+
if (completedData != null) {
|
|
58
|
+
if (!isControllerClosed) {
|
|
59
|
+
controller.enqueue(completedData);
|
|
60
|
+
controller.close();
|
|
61
|
+
isControllerClosed = true;
|
|
62
|
+
}
|
|
63
|
+
response.streamingState = 'completed';
|
|
64
|
+
} else {
|
|
65
|
+
response.streamingState = 'started';
|
|
66
|
+
}
|
|
67
|
+
} else if (response.streamingState === 'completed') {
|
|
68
|
+
controller.close();
|
|
69
|
+
isControllerClosed = true;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
cancel(reason) {
|
|
73
|
+
response.cancelStreaming(String(reason));
|
|
74
|
+
isControllerClosed = true;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return this.bodyStream;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get headers(): Headers {
|
|
82
|
+
return new Headers(this._rawHeaders);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get ok(): boolean {
|
|
86
|
+
return this.status >= 200 && this.status < 300;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public readonly type = 'default';
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* This method is not currently supported by react-native's Blob constructor.
|
|
93
|
+
*/
|
|
94
|
+
async blob(): Promise<Blob> {
|
|
95
|
+
const buffer = await this.arrayBuffer();
|
|
96
|
+
return new Blob([buffer]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async formData(): Promise<UniversalFormData> {
|
|
100
|
+
// Reference implementation:
|
|
101
|
+
// https://chromium.googlesource.com/chromium/src/+/ed9f0b5933cf5ffb413be1ca844de5be140514bf/third_party/blink/renderer/core/fetch/body.cc#120
|
|
102
|
+
const text = await this.text();
|
|
103
|
+
const searchParams = new URLSearchParams(text);
|
|
104
|
+
const formData = new FormData() as UniversalFormData;
|
|
105
|
+
searchParams.forEach((value, key) => {
|
|
106
|
+
formData.append(key, value);
|
|
107
|
+
});
|
|
108
|
+
return formData;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async json(): Promise<any> {
|
|
112
|
+
const text = await this.text();
|
|
113
|
+
return JSON.parse(text);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async bytes(): Promise<Uint8Array> {
|
|
117
|
+
return new Uint8Array(await this.arrayBuffer());
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
toString(): string {
|
|
121
|
+
return `FetchResponse: { status: ${this.status}, statusText: ${this.statusText}, url: ${this.url} }`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
toJSON(): object {
|
|
125
|
+
return {
|
|
126
|
+
status: this.status,
|
|
127
|
+
statusText: this.statusText,
|
|
128
|
+
redirected: this.redirected,
|
|
129
|
+
url: this.url,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
clone(): Response {
|
|
134
|
+
throw new Error('Not implemented');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private finalize = (): void => {
|
|
138
|
+
this.removeListener('readyForJSFinalization', this.finalize);
|
|
139
|
+
|
|
140
|
+
this.abortCleanupFunction();
|
|
141
|
+
|
|
142
|
+
this.removeAllListeners('didReceiveResponseData');
|
|
143
|
+
this.removeAllListeners('didComplete');
|
|
144
|
+
this.removeAllListeners('didFailWithError');
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SharedObject } from 'expo-modules-core';
|
|
2
|
+
|
|
3
|
+
export type NativeHeadersType = [string, string][];
|
|
4
|
+
|
|
5
|
+
export declare class NativeRequest extends SharedObject {
|
|
6
|
+
public start(
|
|
7
|
+
url: string,
|
|
8
|
+
requestInit: NativeRequestInit,
|
|
9
|
+
requestBody: Uint8Array | null
|
|
10
|
+
): Promise<NativeResponse>;
|
|
11
|
+
public cancel(): void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface NativeRequestInit {
|
|
15
|
+
credentials?: RequestCredentials; // same-origin is not supported
|
|
16
|
+
headers?: NativeHeadersType;
|
|
17
|
+
method?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type NativeResponseEvents = {
|
|
21
|
+
didReceiveResponseData(data: Uint8Array): void;
|
|
22
|
+
didComplete(): void;
|
|
23
|
+
didFailWithError(error: string): void;
|
|
24
|
+
readyForJSFinalization(): void;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export declare class NativeResponse extends SharedObject<NativeResponseEvents> {
|
|
28
|
+
readonly bodyUsed: boolean;
|
|
29
|
+
readonly _rawHeaders: NativeHeadersType;
|
|
30
|
+
readonly status: number;
|
|
31
|
+
readonly statusText: string;
|
|
32
|
+
readonly url: string;
|
|
33
|
+
readonly redirected: boolean;
|
|
34
|
+
startStreaming(): Promise<Uint8Array | null>;
|
|
35
|
+
cancelStreaming(reason: string): void;
|
|
36
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
37
|
+
text(): Promise<string>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type NativeHeadersType } from './NativeRequest';
|
|
2
|
+
import { convertFormDataAsync } from './convertFormData';
|
|
3
|
+
import { blobToArrayBufferAsync } from '../../utils/blobUtils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* convert a ReadableStream to a Uint8Array
|
|
7
|
+
*/
|
|
8
|
+
export async function convertReadableStreamToUint8ArrayAsync(
|
|
9
|
+
stream: ReadableStream<Uint8Array>
|
|
10
|
+
): Promise<Uint8Array> {
|
|
11
|
+
const reader = stream.getReader();
|
|
12
|
+
const chunks: Uint8Array[] = [];
|
|
13
|
+
let totalLength = 0;
|
|
14
|
+
|
|
15
|
+
// Read all chunks from the stream
|
|
16
|
+
while (true) {
|
|
17
|
+
const { done, value } = await reader.read();
|
|
18
|
+
if (done) break;
|
|
19
|
+
chunks.push(value);
|
|
20
|
+
totalLength += value.length;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Concatenate all chunks into a single Uint8Array
|
|
24
|
+
const result = new Uint8Array(totalLength);
|
|
25
|
+
let offset = 0;
|
|
26
|
+
for (const chunk of chunks) {
|
|
27
|
+
result.set(chunk, offset);
|
|
28
|
+
offset += chunk.length;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a BodyInit object to a Uint8Array for NativeRequest
|
|
36
|
+
*/
|
|
37
|
+
export async function normalizeBodyInitAsync(
|
|
38
|
+
body: BodyInit | null | undefined
|
|
39
|
+
): Promise<{ body: Uint8Array | null; overriddenHeaders?: NativeHeadersType }> {
|
|
40
|
+
if (body == null) {
|
|
41
|
+
return { body: null };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (typeof body === 'string') {
|
|
45
|
+
const encoder = new TextEncoder();
|
|
46
|
+
return { body: encoder.encode(body) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (body instanceof ArrayBuffer) {
|
|
50
|
+
return { body: new Uint8Array(body) };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (ArrayBuffer.isView(body)) {
|
|
54
|
+
return { body: new Uint8Array(body.buffer, body.byteOffset, body.byteLength) };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (body instanceof Blob) {
|
|
58
|
+
return {
|
|
59
|
+
body: new Uint8Array(await blobToArrayBufferAsync(body)),
|
|
60
|
+
overriddenHeaders: [['Content-Type', body.type]],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (body instanceof URLSearchParams) {
|
|
65
|
+
const encoder = new TextEncoder();
|
|
66
|
+
return { body: encoder.encode(body.toString()) };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (body instanceof ReadableStream) {
|
|
70
|
+
const result = await convertReadableStreamToUint8ArrayAsync(body);
|
|
71
|
+
return { body: result };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (body instanceof FormData) {
|
|
75
|
+
const { body: result, boundary } = await convertFormDataAsync(body);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
body: result,
|
|
79
|
+
overriddenHeaders: [['Content-Type', `multipart/form-data; boundary=${boundary}`]],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
throw new TypeError('Unsupported BodyInit type');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Normalize a HeadersInit object to an array of key-value tuple for NativeRequest.
|
|
88
|
+
*/
|
|
89
|
+
export function normalizeHeadersInit(headers: HeadersInit | null | undefined): NativeHeadersType {
|
|
90
|
+
if (headers == null) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
if (Array.isArray(headers)) {
|
|
94
|
+
return headers;
|
|
95
|
+
}
|
|
96
|
+
if (headers instanceof Headers) {
|
|
97
|
+
const results: [string, string][] = [];
|
|
98
|
+
headers.forEach((value: any, key: any) => {
|
|
99
|
+
results.push([key, value]);
|
|
100
|
+
});
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
return Object.entries(headers);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Create a new header array by overriding the existing headers with new headers (by header key).
|
|
108
|
+
*/
|
|
109
|
+
export function overrideHeaders(
|
|
110
|
+
headers: NativeHeadersType,
|
|
111
|
+
newHeaders: NativeHeadersType
|
|
112
|
+
): NativeHeadersType {
|
|
113
|
+
const newKeySet = new Set(newHeaders.map(([key]) => key.toLocaleLowerCase()));
|
|
114
|
+
const result: NativeHeadersType = [];
|
|
115
|
+
for (const [key, value] of headers) {
|
|
116
|
+
if (!newKeySet.has(key.toLocaleLowerCase())) {
|
|
117
|
+
result.push([key, value]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const [key, value] of newHeaders) {
|
|
121
|
+
result.push([key, value]);
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { blobToArrayBufferAsync } from '../../utils/blobUtils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert FormData to Uint8Array with a boundary
|
|
5
|
+
*
|
|
6
|
+
* `uri` is not supported for React Native's FormData.
|
|
7
|
+
* `blob` is not supported for standard FormData.
|
|
8
|
+
*/
|
|
9
|
+
export async function convertFormDataAsync(
|
|
10
|
+
formData: FormData,
|
|
11
|
+
boundary: string = createBoundary()
|
|
12
|
+
): Promise<{ body: Uint8Array; boundary: string }> {
|
|
13
|
+
// @ts-expect-error: React Native's FormData is not compatible with the web's FormData
|
|
14
|
+
if (typeof formData.getParts !== 'function') {
|
|
15
|
+
throw new Error('Unsupported FormData implementation');
|
|
16
|
+
}
|
|
17
|
+
// @ts-expect-error: React Native's FormData is not 100% compatible with ours
|
|
18
|
+
const parts: ExpoFormDataPart[] = formData.getParts();
|
|
19
|
+
|
|
20
|
+
const results: (Uint8Array | string)[] = [];
|
|
21
|
+
for (const entry of parts) {
|
|
22
|
+
results.push(`--${boundary}\r\n`);
|
|
23
|
+
for (const [headerKey, headerValue] of Object.entries(entry.headers)) {
|
|
24
|
+
results.push(`${headerKey}: ${headerValue}\r\n`);
|
|
25
|
+
}
|
|
26
|
+
results.push(`\r\n`);
|
|
27
|
+
if ('string' in entry) {
|
|
28
|
+
results.push(entry.string);
|
|
29
|
+
} else if ('file' in entry) {
|
|
30
|
+
results.push(entry.file.bytes());
|
|
31
|
+
} else if ('blob' in entry) {
|
|
32
|
+
results.push(new Uint8Array(await blobToArrayBufferAsync(entry.blob)));
|
|
33
|
+
} else if (entry._data?.blobId != null) {
|
|
34
|
+
// When `FormData.getParts()` is called, React Native will use the spread syntax to copy the object and lose the Blob type info.
|
|
35
|
+
// We should find the original Blob instance from the `FormData._parts` internal properties.
|
|
36
|
+
// @ts-expect-error: react-native's proprietary Blob type
|
|
37
|
+
const formDatum = formData._parts?.find(
|
|
38
|
+
([_name, value]: [name: string, value: any]) => value.data?.blobId === entry._data.blobId
|
|
39
|
+
);
|
|
40
|
+
if (formDatum == null) {
|
|
41
|
+
throw new Error('Cannot find the original Blob instance from FormData');
|
|
42
|
+
}
|
|
43
|
+
if (!(formDatum[1] instanceof Blob)) {
|
|
44
|
+
throw new Error('Unexpected value type for Blob entry in FormData');
|
|
45
|
+
}
|
|
46
|
+
results.push(new Uint8Array(await blobToArrayBufferAsync(formDatum[1])));
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error('Unsupported FormDataPart implementation');
|
|
49
|
+
}
|
|
50
|
+
results.push(`\r\n`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
results.push(`--${boundary}--\r\n`);
|
|
54
|
+
const arrays = results.map((result) => {
|
|
55
|
+
if (typeof result === 'string') {
|
|
56
|
+
// @ts-ignore: TextEncoder is not available in all environments
|
|
57
|
+
return new TextEncoder().encode(result);
|
|
58
|
+
} else {
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
}) as Uint8Array[];
|
|
62
|
+
|
|
63
|
+
return { body: joinUint8Arrays(arrays), boundary };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create mutipart boundary
|
|
68
|
+
*/
|
|
69
|
+
export function createBoundary(): string {
|
|
70
|
+
const boundaryChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
71
|
+
let boundary = '----ExpoFetchFormBoundary';
|
|
72
|
+
for (let i = 0; i < 16; i++) {
|
|
73
|
+
boundary += boundaryChars.charAt(Math.floor(Math.random() * boundaryChars.length));
|
|
74
|
+
}
|
|
75
|
+
return boundary;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Merge Uint8Arrays into a single Uint8Array
|
|
80
|
+
*/
|
|
81
|
+
export function joinUint8Arrays(arrays: Uint8Array[]): Uint8Array {
|
|
82
|
+
const totalLength: number = arrays.reduce((acc: number, arr: Uint8Array) => acc + arr.length, 0);
|
|
83
|
+
const result: Uint8Array = new Uint8Array(totalLength);
|
|
84
|
+
|
|
85
|
+
let offset: number = 0;
|
|
86
|
+
arrays.forEach((array: Uint8Array) => {
|
|
87
|
+
result.set(array, offset);
|
|
88
|
+
offset += array.length;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ExpoFetchModule } from './ExpoFetchModule';
|
|
2
|
+
import { FetchError } from './FetchErrors';
|
|
3
|
+
import { FetchResponse, type AbortSubscriptionCleanupFunction } from './FetchResponse';
|
|
4
|
+
import { NativeRequest, NativeRequestInit } from './NativeRequest';
|
|
5
|
+
import { normalizeBodyInitAsync, normalizeHeadersInit, overrideHeaders } from './RequestUtils';
|
|
6
|
+
import type { FetchRequestInit } from './fetch.types';
|
|
7
|
+
|
|
8
|
+
// TODO(@kitten): Do we really want to use our own types for web standards?
|
|
9
|
+
export async function fetch(url: string, init?: FetchRequestInit): Promise<FetchResponse> {
|
|
10
|
+
let abortSubscription: AbortSubscriptionCleanupFunction | null = null;
|
|
11
|
+
|
|
12
|
+
const response = new FetchResponse(() => {
|
|
13
|
+
abortSubscription?.();
|
|
14
|
+
});
|
|
15
|
+
const request = new ExpoFetchModule.NativeRequest(response) as NativeRequest;
|
|
16
|
+
|
|
17
|
+
let headers = normalizeHeadersInit(init?.headers);
|
|
18
|
+
|
|
19
|
+
const { body: requestBody, overriddenHeaders } = await normalizeBodyInitAsync(init?.body);
|
|
20
|
+
if (overriddenHeaders) {
|
|
21
|
+
headers = overrideHeaders(headers, overriddenHeaders);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const nativeRequestInit: NativeRequestInit = {
|
|
25
|
+
credentials: init?.credentials ?? 'include',
|
|
26
|
+
headers,
|
|
27
|
+
method: init?.method ?? 'GET',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (init?.signal && init.signal.aborted) {
|
|
31
|
+
throw new FetchError('The operation was aborted.');
|
|
32
|
+
}
|
|
33
|
+
abortSubscription = addAbortSignalListener(init?.signal, () => {
|
|
34
|
+
request.cancel();
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
await request.start(url, nativeRequestInit, requestBody);
|
|
38
|
+
} catch (e: unknown) {
|
|
39
|
+
if (e instanceof Error) {
|
|
40
|
+
throw FetchError.createFromError(e);
|
|
41
|
+
} else {
|
|
42
|
+
throw new FetchError(String(e));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return response;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A wrapper of `AbortSignal.addEventListener` that returns a cleanup function.
|
|
50
|
+
*/
|
|
51
|
+
function addAbortSignalListener(
|
|
52
|
+
signal: AbortSignal | undefined,
|
|
53
|
+
listener: Parameters<AbortSignal['addEventListener']>[1]
|
|
54
|
+
): AbortSubscriptionCleanupFunction {
|
|
55
|
+
signal?.addEventListener('abort', listener);
|
|
56
|
+
return () => {
|
|
57
|
+
signal?.removeEventListener('abort', listener);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fetch RequestInit compatible structure.
|
|
3
|
+
*/
|
|
4
|
+
export interface FetchRequestInit {
|
|
5
|
+
body?: BodyInit;
|
|
6
|
+
credentials?: RequestCredentials; // same-origin is not supported
|
|
7
|
+
headers?: HeadersInit;
|
|
8
|
+
method?: string;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
|
|
11
|
+
// Not supported fields
|
|
12
|
+
integrity?: string;
|
|
13
|
+
keepalive?: boolean;
|
|
14
|
+
mode?: RequestMode;
|
|
15
|
+
referrer?: string;
|
|
16
|
+
window?: any;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const fetch = globalThis.fetch;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './runtime';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// This file configures the runtime environment to increase compatibility with WinterCG.
|
|
2
|
+
// https://wintercg.org/
|
|
3
|
+
|
|
4
|
+
// @ts-ignore: PolyfillFunctions does not have types exported
|
|
5
|
+
import { polyfillGlobal as installGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctions';
|
|
6
|
+
|
|
7
|
+
import { installFormDataPatch } from './FormData';
|
|
8
|
+
// Add a well-known shared symbol that doesn't show up in iteration or inspection
|
|
9
|
+
// this can be used to detect if the global object abides by the Expo team's documented
|
|
10
|
+
// built-in requirements.
|
|
11
|
+
const BUILTIN_SYMBOL = Symbol.for('expo.builtin');
|
|
12
|
+
|
|
13
|
+
function addBuiltinSymbol(obj: object) {
|
|
14
|
+
Object.defineProperty(obj, BUILTIN_SYMBOL, {
|
|
15
|
+
value: true,
|
|
16
|
+
enumerable: false,
|
|
17
|
+
configurable: false,
|
|
18
|
+
});
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function install(name: string, getValue: () => any) {
|
|
23
|
+
installGlobal(name, () => addBuiltinSymbol(getValue()));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// https://encoding.spec.whatwg.org/#textdecoder
|
|
27
|
+
install('TextDecoder', () => require('./TextDecoder').TextDecoder);
|
|
28
|
+
// https://url.spec.whatwg.org/#url
|
|
29
|
+
install('URL', () => require('./url').URL);
|
|
30
|
+
// https://url.spec.whatwg.org/#urlsearchparams
|
|
31
|
+
install('URLSearchParams', () => require('./url').URLSearchParams);
|
|
32
|
+
// https://streams.spec.whatwg.org/#rs
|
|
33
|
+
// ReadableStream is injected by Metro as a global
|
|
34
|
+
|
|
35
|
+
install('__ExpoImportMetaRegistry', () => require('./ImportMetaRegistry').ImportMetaRegistry);
|
|
36
|
+
|
|
37
|
+
installFormDataPatch(FormData);
|
|
38
|
+
|
|
39
|
+
// Polyfill async iterator symbol for Hermes.
|
|
40
|
+
// @ts-expect-error: readonly property only applies when the engine supports it
|
|
41
|
+
Symbol.asyncIterator ??= Symbol.for('Symbol.asyncIterator');
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © 2023-present 650 Industries, Inc. (aka Expo)
|
|
3
|
+
* Copyright © Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// This file should not import `react-native` in order to remain self-contained.
|
|
10
|
+
|
|
11
|
+
/// <reference path="../ts-declarations/whatwg-url-without-unicode.d.ts" />
|
|
12
|
+
import { URL, URLSearchParams } from 'whatwg-url-without-unicode';
|
|
13
|
+
|
|
14
|
+
declare namespace globalThis {
|
|
15
|
+
const RN$Bridgeless: undefined | boolean;
|
|
16
|
+
const nativeModuleProxy: Record<string, unknown>;
|
|
17
|
+
function __turboModuleProxy(name: string): unknown;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// TODO(@kitten): Provide BlobModule types matching native module
|
|
21
|
+
interface NativeBlobModule {
|
|
22
|
+
BLOB_URI_SCHEME: string;
|
|
23
|
+
BLOB_URI_HOST: string;
|
|
24
|
+
}
|
|
25
|
+
interface TurboBlobModule {
|
|
26
|
+
getConstants(): {
|
|
27
|
+
BLOB_URI_SCHEME: string;
|
|
28
|
+
BLOB_URI_HOST: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let isSetup = false;
|
|
33
|
+
let BLOB_URL_PREFIX: string | null = null;
|
|
34
|
+
|
|
35
|
+
function getBlobUrlPrefix() {
|
|
36
|
+
if (isSetup) return BLOB_URL_PREFIX;
|
|
37
|
+
isSetup = true;
|
|
38
|
+
// if iOS: let BLOB_URL_PREFIX = 'blob:'
|
|
39
|
+
|
|
40
|
+
// Pull the blob module without importing React Native.
|
|
41
|
+
const BlobModule =
|
|
42
|
+
globalThis.RN$Bridgeless !== true
|
|
43
|
+
? // Legacy RN implementation
|
|
44
|
+
(globalThis.nativeModuleProxy['BlobModule'] as NativeBlobModule)
|
|
45
|
+
: // Newer RN implementation
|
|
46
|
+
(globalThis.__turboModuleProxy('BlobModule') as TurboBlobModule);
|
|
47
|
+
|
|
48
|
+
const constants = 'BLOB_URI_SCHEME' in BlobModule ? BlobModule : BlobModule.getConstants();
|
|
49
|
+
|
|
50
|
+
if (constants && typeof constants.BLOB_URI_SCHEME === 'string') {
|
|
51
|
+
BLOB_URL_PREFIX = encodeURIComponent(constants.BLOB_URI_SCHEME) + ':';
|
|
52
|
+
if (typeof constants.BLOB_URI_HOST === 'string') {
|
|
53
|
+
BLOB_URL_PREFIX += `//${encodeURIComponent(constants.BLOB_URI_HOST)}/`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return BLOB_URL_PREFIX;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
declare module 'whatwg-url-without-unicode' {
|
|
60
|
+
// TODO(@kitten): Clarify where this came from
|
|
61
|
+
type BlobLike = Blob & { data?: { blobId: string; offset: number } };
|
|
62
|
+
|
|
63
|
+
interface URLConstructor {
|
|
64
|
+
createObjectURL(blob: BlobLike): string;
|
|
65
|
+
revokeObjectURL(url: URL): void;
|
|
66
|
+
canParse(url: string, base?: string): boolean;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* To allow Blobs be accessed via `content://` URIs,
|
|
72
|
+
* you need to register `BlobProvider` as a ContentProvider in your app's `AndroidManifest.xml`:
|
|
73
|
+
*
|
|
74
|
+
* ```xml
|
|
75
|
+
* <manifest>
|
|
76
|
+
* <application>
|
|
77
|
+
* <provider
|
|
78
|
+
* android:name="com.facebook.react.modules.blob.BlobProvider"
|
|
79
|
+
* android:authorities="@string/blob_provider_authority"
|
|
80
|
+
* android:exported="false"
|
|
81
|
+
* />
|
|
82
|
+
* </application>
|
|
83
|
+
* </manifest>
|
|
84
|
+
* ```
|
|
85
|
+
* And then define the `blob_provider_authority` string in `res/values/strings.xml`.
|
|
86
|
+
* Use a dotted name that's entirely unique to your app:
|
|
87
|
+
*
|
|
88
|
+
* ```xml
|
|
89
|
+
* <resources>
|
|
90
|
+
* <string name="blob_provider_authority">your.app.package.blobs</string>
|
|
91
|
+
* </resources>
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
URL.createObjectURL = function createObjectURL(blob) {
|
|
95
|
+
if (getBlobUrlPrefix() == null) {
|
|
96
|
+
throw new Error('Cannot create URL for blob');
|
|
97
|
+
}
|
|
98
|
+
return `${getBlobUrlPrefix()}${encodeURIComponent(blob.data!.blobId)}?offset=${encodeURIComponent(
|
|
99
|
+
blob.data!.offset
|
|
100
|
+
)}&size=${encodeURIComponent(blob.size)}`;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
URL.revokeObjectURL = function revokeObjectURL(_url) {
|
|
104
|
+
// Do nothing.
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
URL.canParse = function canParse(url: string, base?: string): boolean {
|
|
108
|
+
try {
|
|
109
|
+
URL(url, base);
|
|
110
|
+
return true;
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export { URL, URLSearchParams };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
// Extend the NodeJS namespace
|
|
4
|
+
declare namespace NodeJS {
|
|
5
|
+
interface ProcessEnv {
|
|
6
|
+
readonly NODE_ENV: 'development' | 'production' | 'test';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Create types for CSS modules
|
|
11
|
+
declare module '*.module.css' {
|
|
12
|
+
/** **Experimental:** Import styles that can be used with `react-native-web` components, using the `style` prop. */
|
|
13
|
+
export const unstable_styles: { readonly [key: string]: object };
|
|
14
|
+
|
|
15
|
+
const classes: { readonly [key: string]: string };
|
|
16
|
+
export default classes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module '*.module.sass' {
|
|
20
|
+
/** **Experimental:** Import styles that can be used with `react-native-web` components, using the `style` prop. */
|
|
21
|
+
export const unstable_styles: { readonly [key: string]: object };
|
|
22
|
+
|
|
23
|
+
const classes: { readonly [key: string]: string };
|
|
24
|
+
export default classes;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare module '*.module.scss' {
|
|
28
|
+
/** **Experimental:** Import styles that can be used with `react-native-web` components, using the `style` prop. */
|
|
29
|
+
export const unstable_styles: { readonly [key: string]: object };
|
|
30
|
+
|
|
31
|
+
const classes: { readonly [key: string]: string };
|
|
32
|
+
export default classes;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Allow for css imports, but don't export anything
|
|
36
|
+
declare module '*.css';
|
|
37
|
+
declare module '*.sass';
|
|
38
|
+
declare module '*.scss';
|