1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {Thenable} from 'shared/ReactTypes.js';
    
  11. 
    
  12. import type {Response as FlightResponse} from 'react-client/src/ReactFlightClient';
    
  13. 
    
  14. import type {ReactServerValue} from 'react-client/src/ReactFlightReplyClient';
    
  15. 
    
  16. import {
    
  17.   createResponse,
    
  18.   getRoot,
    
  19.   reportGlobalError,
    
  20.   processBinaryChunk,
    
  21.   close,
    
  22. } from 'react-client/src/ReactFlightClient';
    
  23. 
    
  24. import {
    
  25.   processReply,
    
  26.   createServerReference,
    
  27. } from 'react-client/src/ReactFlightReplyClient';
    
  28. 
    
  29. type CallServerCallback = <A, T>(string, args: A) => Promise<T>;
    
  30. 
    
  31. export type Options = {
    
  32.   moduleBaseURL?: string,
    
  33.   callServer?: CallServerCallback,
    
  34. };
    
  35. 
    
  36. function createResponseFromOptions(options: void | Options) {
    
  37.   return createResponse(
    
  38.     options && options.moduleBaseURL ? options.moduleBaseURL : '',
    
  39.     null,
    
  40.     options && options.callServer ? options.callServer : undefined,
    
  41.     undefined, // nonce
    
  42.   );
    
  43. }
    
  44. 
    
  45. function startReadingFromStream(
    
  46.   response: FlightResponse,
    
  47.   stream: ReadableStream,
    
  48. ): void {
    
  49.   const reader = stream.getReader();
    
  50.   function progress({
    
  51.     done,
    
  52.     value,
    
  53.   }: {
    
  54.     done: boolean,
    
  55.     value: ?any,
    
  56.     ...
    
  57.   }): void | Promise<void> {
    
  58.     if (done) {
    
  59.       close(response);
    
  60.       return;
    
  61.     }
    
  62.     const buffer: Uint8Array = (value: any);
    
  63.     processBinaryChunk(response, buffer);
    
  64.     return reader.read().then(progress).catch(error);
    
  65.   }
    
  66.   function error(e: any) {
    
  67.     reportGlobalError(response, e);
    
  68.   }
    
  69.   reader.read().then(progress).catch(error);
    
  70. }
    
  71. 
    
  72. function createFromReadableStream<T>(
    
  73.   stream: ReadableStream,
    
  74.   options?: Options,
    
  75. ): Thenable<T> {
    
  76.   const response: FlightResponse = createResponseFromOptions(options);
    
  77.   startReadingFromStream(response, stream);
    
  78.   return getRoot(response);
    
  79. }
    
  80. 
    
  81. function createFromFetch<T>(
    
  82.   promiseForResponse: Promise<Response>,
    
  83.   options?: Options,
    
  84. ): Thenable<T> {
    
  85.   const response: FlightResponse = createResponseFromOptions(options);
    
  86.   promiseForResponse.then(
    
  87.     function (r) {
    
  88.       startReadingFromStream(response, (r.body: any));
    
  89.     },
    
  90.     function (e) {
    
  91.       reportGlobalError(response, e);
    
  92.     },
    
  93.   );
    
  94.   return getRoot(response);
    
  95. }
    
  96. 
    
  97. function encodeReply(
    
  98.   value: ReactServerValue,
    
  99. ): Promise<
    
  100.   string | URLSearchParams | FormData,
    
  101. > /* We don't use URLSearchParams yet but maybe */ {
    
  102.   return new Promise((resolve, reject) => {
    
  103.     processReply(value, '', resolve, reject);
    
  104.   });
    
  105. }
    
  106. 
    
  107. export {
    
  108.   createFromFetch,
    
  109.   createFromReadableStream,
    
  110.   encodeReply,
    
  111.   createServerReference,
    
  112. };