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.   callServer?: CallServerCallback,
    
  33. };
    
  34. 
    
  35. function createResponseFromOptions(options: void | Options) {
    
  36.   return createResponse(
    
  37.     null,
    
  38.     null,
    
  39.     options && options.callServer ? options.callServer : undefined,
    
  40.     undefined, // nonce
    
  41.   );
    
  42. }
    
  43. 
    
  44. function startReadingFromStream(
    
  45.   response: FlightResponse,
    
  46.   stream: ReadableStream,
    
  47. ): void {
    
  48.   const reader = stream.getReader();
    
  49.   function progress({
    
  50.     done,
    
  51.     value,
    
  52.   }: {
    
  53.     done: boolean,
    
  54.     value: ?any,
    
  55.     ...
    
  56.   }): void | Promise<void> {
    
  57.     if (done) {
    
  58.       close(response);
    
  59.       return;
    
  60.     }
    
  61.     const buffer: Uint8Array = (value: any);
    
  62.     processBinaryChunk(response, buffer);
    
  63.     return reader.read().then(progress).catch(error);
    
  64.   }
    
  65.   function error(e: any) {
    
  66.     reportGlobalError(response, e);
    
  67.   }
    
  68.   reader.read().then(progress).catch(error);
    
  69. }
    
  70. 
    
  71. function createFromReadableStream<T>(
    
  72.   stream: ReadableStream,
    
  73.   options?: Options,
    
  74. ): Thenable<T> {
    
  75.   const response: FlightResponse = createResponseFromOptions(options);
    
  76.   startReadingFromStream(response, stream);
    
  77.   return getRoot(response);
    
  78. }
    
  79. 
    
  80. function createFromFetch<T>(
    
  81.   promiseForResponse: Promise<Response>,
    
  82.   options?: Options,
    
  83. ): Thenable<T> {
    
  84.   const response: FlightResponse = createResponseFromOptions(options);
    
  85.   promiseForResponse.then(
    
  86.     function (r) {
    
  87.       startReadingFromStream(response, (r.body: any));
    
  88.     },
    
  89.     function (e) {
    
  90.       reportGlobalError(response, e);
    
  91.     },
    
  92.   );
    
  93.   return getRoot(response);
    
  94. }
    
  95. 
    
  96. function encodeReply(
    
  97.   value: ReactServerValue,
    
  98. ): Promise<
    
  99.   string | URLSearchParams | FormData,
    
  100. > /* We don't use URLSearchParams yet but maybe */ {
    
  101.   return new Promise((resolve, reject) => {
    
  102.     processReply(value, '', resolve, reject);
    
  103.   });
    
  104. }
    
  105. 
    
  106. export {
    
  107.   createFromFetch,
    
  108.   createFromReadableStream,
    
  109.   encodeReply,
    
  110.   createServerReference,
    
  111. };