Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redundant piecemeal copying of fetch response #89

Open
github-actions bot opened this issue Dec 29, 2024 · 2 comments
Open

Redundant piecemeal copying of fetch response #89

github-actions bot opened this issue Dec 29, 2024 · 2 comments
Assignees
Labels
datadirect-puppeteer packages/datadirect-puppeteer types TypeScript type definition improvement

Comments

@github-actions
Copy link

// TODO There has got to be some type magic that makes this manual copying unnecessary

import { Endpoint } from 'datadirect';
import { Authenticated } from './Authenticated.js';

type EndpointOptions<P extends Endpoint.Payload> = {
  payload: P;
  pathParams?: Record<string, string | number | boolean>;
  logBodyOnError?: boolean;
};

export type BoundEndpoint<
  P extends Endpoint.Payload,
  R extends Endpoint.Response
> = (options: EndpointOptions<P>) => Promise<R>;

type FetchError = {
  error: Error;
  response: Response;
  body: string;
} & Endpoint.FetchParams;

function isFetchError(e: unknown): e is FetchError {
  return e != null && typeof e === 'object' && 'error' in e && 'body' in e;
}

export class Fetchable extends Authenticated {
  protected bindEndpoint<
    P extends Endpoint.Payload,
    R extends Endpoint.Response
  >(module: Endpoint.Module<P>): BoundEndpoint<P, R> {
    return async ({
      payload,
      pathParams = {},
      logBodyOnError = false
    }: EndpointOptions<P>) => {
      const { input, init } = module.prepare(payload, this.page.url());
      const result: R | FetchError = await this.page.evaluate(
        async (params) => {
          const { input, init } = params;
          let body: R | undefined | string = undefined;
          let response: Response | undefined = undefined;
          try {
            response = await fetch(input, init);
            body = await response.text();
            return JSON.parse(body) as R;
          } catch (error) {
            return {
              error: error as Error,
              input,
              init,
              // TODO There has got to be some type magic that makes this manual copying unnecessary
              response: {
                url: response?.url,
                redirected: response?.redirected,
                type: response?.type,
                status: response?.status,
                statusText: response?.statusText,
                headers: response?.headers
              },
              body
            } as FetchError;
          }
        },
        { input: Endpoint.preparePath(input, pathParams), init }
      );
      if (isFetchError(result)) {
        const { error, body, ...rest } = result;
        if (logBodyOnError) {
          console.error(rest);
          console.error(body);
        }
        throw error;
      }
      return result;
    };
  }
}
@battis battis added datadirect-puppeteer packages/datadirect-puppeteer types TypeScript type definition improvement labels Dec 29, 2024
Copy link
Author

Closed in 910eb47.

@battis
Copy link
Owner

battis commented Dec 31, 2024

Not closed, just moved

return {
url: response.url,
redirected: response.redirected,
type: response.type,
status: response.status,
statusText: response.statusText,
headers: response.headers,
body
};

@battis battis reopened this Dec 31, 2024
@battis battis changed the title There has got to be some type magic that makes this manual copying unnecessary Redundant piecemeal copying of fetch response Jan 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
datadirect-puppeteer packages/datadirect-puppeteer types TypeScript type definition improvement
Projects
None yet
Development

No branches or pull requests

1 participant