next#NextPageContext TypeScript Examples

The following examples show how to use next#NextPageContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
MapPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
    pathname: ctx.pathname,
  };
};
Example #2
Source File: makeContextObject.ts    From next-page-tester with MIT License 6 votes vote down vote up
export function makeGetInitialPropsContext({
  pageObject,
  options: { req: reqMocker, res: resMocker, previousRoute, env },
}: {
  pageObject: PageObject;
  options: ExtendedOptions;
}): NextPageContext {
  const { pagePath, params, route, query } = pageObject;

  const ctx: NextPageContext = {
    // @NOTE AppTree is currently just a stub
    AppTree: Fragment,
    pathname: pagePath,
    query: { ...params, ...query }, // GIP ctx query merges params and query together
    asPath: route,
  };

  if (env === 'server') {
    const { req, res } = makeHttpObjects({
      pageObject,
      reqMocker,
      resMocker,
      refererRoute: previousRoute,
    });

    ctx.req = req;
    ctx.res = res;
  }

  return ctx;
}
Example #3
Source File: _error.tsx    From crosshare with GNU Affero General Public License v3.0 6 votes vote down vote up
MyError.getInitialProps = async ({ res, err, asPath }: NextPageContext) => {
  const errorInitialProps: ErrorProps = await NextErrorComponent.getInitialProps(
    { res, err } as NextPageContext
  );

  // Running on the server, the response object (`res`) is available.
  //
  // Next.js will pass an err on the server if a page's data fetching methods
  // threw or returned a Promise that rejected
  //
  // Running on the client (browser), Next.js will provide an err if:
  //
  //  - a page's `getInitialProps` threw or returned a Promise that rejected
  //  - an exception was thrown somewhere in the React lifecycle (render,
  //    componentDidMount, etc) that was caught by Next.js's React Error
  //    Boundary. Read more about what types of exceptions are caught by Error
  //    Boundaries: https://reactjs.org/docs/error-boundaries.html

  if (res?.statusCode === 404) {
    return { statusCode: 404 };
  }
  if (err && typeof Sentry !== 'undefined') {
    if (!isLocalStorageError(err)) {
      Sentry.captureException(err);
    }
    return { ...errorInitialProps, hasGetInitialPropsRun: true };
  }

  // If this point is reached, getInitialProps was called without any
  // information about what the error might be. This is unexpected and may
  // indicate a bug introduced in Next.js, so record it in Sentry
  if (typeof Sentry !== 'undefined') {
    Sentry.captureException(
      new Error(`_error.js getInitialProps missing data at path: ${asPath}`)
    );
  }

  return { ...errorInitialProps, hasGetInitialPropsRun: true };
};
Example #4
Source File: _error.tsx    From rcvr-app with GNU Affero General Public License v3.0 6 votes vote down vote up
Error.getInitialProps = async (ctx: NextPageContext): Promise<ErrorProps> => {
  const { req, res, err } = ctx
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404

  if (typeof window === 'undefined') {
    /**
     * Redirect trailing slashes to non-trailing slashes
     * Workaround for: https://github.com/zeit/next.js/issues/8913#issuecomment-537632531
     * Test vectors:
     * `/test/test/` -> `/test/test`
     * `/test/////test////` -> `/test/test`
     * `/test//test//?a=1&b=2` -> `/test?a=1&b=2`
     * `/test///#test` -> `/test#test`
     */
    const normalizedPath = normalizePath(req.url)
    if (req && res && req.url && normalizedPath !== req.url) {
      res.writeHead(302, { Location: normalizedPath })
      res.end()
    }
  }

  return { statusCode, error: err }
}
Example #5
Source File: index.tsx    From core with GNU Affero General Public License v3.0 6 votes vote down vote up
getServerSideProps = async (ctx: NextPageContext) => {
	const parsed = parseCookie(ctx.req)
	const user = await get.Authorization(parsed?.token)
	const guilds = (await get.userGuilds.load(user || ''))?.filter(g=> (g.permissions & 8) || g.owner).map(async g => {
		const server = (await get.server.load(g.id))
		const data = await get.serverData(g.id)
		return { ...g, ...(server || {}), ...((+new Date() - +new Date(data?.updatedAt)) < 2 * 60 * 1000  ? { data } : {}), members: data?.memberCount || null, exists: !!server }
	})
	return { props: { logged: !!user || !!guilds, user: await get.user.load(user || ''), guilds: guilds ? (await Promise.all(guilds)).filter(g => !g?.exists) : null } }
}
Example #6
Source File: [id].tsx    From core with GNU Affero General Public License v3.0 6 votes vote down vote up
getServerSideProps = async (ctx: NextPageContext) => {
	const parsed = parseCookie(ctx.req)
	const user = await get.Authorization(parsed?.token)
	const server = await get.server.load(ctx.query.id as string) || null
	const serverData = await get.serverData(ctx.query.id as string) || null
	return { props: {
		logged: !!user, user: await get.user.load(user || ''),
		csrfToken: getToken(ctx.req, ctx.res),
		server,
		serverData: (+new Date() - +new Date(serverData?.updatedAt)) < 2 * 60 * 1000 ? serverData : null
	} }
}
Example #7
Source File: _error.tsx    From frontend.ro with MIT License 6 votes vote down vote up
Error.getInitialProps = ({ res, err }: NextPageContext) => {
  // Default code
  let statusCode = 500;

  if (res) {
    statusCode = res.statusCode;
  } else if (err) {
    statusCode = err.statusCode;
  } else {
    console.error('[Error.getInitialProps] Neither `res` nor `err` are defined. ');
  }

  return { statusCode };
};
Example #8
Source File: getApiUrl.ts    From selftrace with MIT License 6 votes vote down vote up
export default function getApiUrl(path: string, ctx: NextPageContext) {
  let { req } = ctx;
  if (!req && typeof window !== 'undefined') return `/api${path}`;

  const host = req ? req.headers['x-forwarded-host'] || req.headers.host : window.location.host;
  const proto = req
    ? req.headers['x-forwarded-proto'] || 'http'
    : window.location.protocol.slice(0, -1);
  return `${proto}://${host}/api${path}`;
}
Example #9
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
SignupPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
  };
};
Example #10
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
ResetPasswordPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
  };
};
Example #11
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
LoginPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
  };
};
Example #12
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
FormPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
    pathname: ctx.pathname,
  };
};
Example #13
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
UpdatePasswordPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
  };
};
Example #14
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
ProfilePage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
  };
};
Example #15
Source File: index.tsx    From selftrace with MIT License 6 votes vote down vote up
AccountPage.getInitialProps = async (ctx: NextPageContext) => {
  // do async stuff here to load data
  // ctx.query is the ?params
  // eg:
  // let url = getApiUrl(urlWithQuery('/libraries', ctx.query), ctx);
  // let response = await fetch(url);
  // let result = await response.json();

  return {
    // data: result,
    // query: ctx.query,
    pathname: ctx.pathname,
  };
};
Example #16
Source File: withApollo.ts    From lireddit with MIT License 6 votes vote down vote up
createClient = (ctx: NextPageContext) =>
  new ApolloClient({
    uri: process.env.NEXT_PUBLIC_API_URL as string,
    credentials: "include",
    headers: {
      cookie:
        (typeof window === "undefined"
          ? ctx?.req?.headers.cookie
          : undefined) || "",
    },
    cache: new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            posts: {
              keyArgs: [],
              merge(
                existing: PaginatedPosts | undefined,
                incoming: PaginatedPosts
              ): PaginatedPosts {
                return {
                  ...incoming,
                  posts: [...(existing?.posts || []), ...incoming.posts],
                };
              },
            },
          },
        },
      },
    }),
  })
Example #17
Source File: [slug].tsx    From storefront with MIT License 6 votes vote down vote up
Page.getInitialProps = async (
  context: NextPageContext & { apolloClient: ApolloClient<NormalizedCacheObject> },
) => {
  const page = await context.apolloClient
    .query<PageQuery, PageQueryVariables>({
      query: PageDocument,
      variables: {
        slug: `${context.query.slug}`,
      },
    })
    .then(({ data }) => {
      if (context.res != null && data?.page == null) {
        context.res.statusCode = 404;
      }
      return data?.page;
    });
  return { page };
};
Example #18
Source File: _document.tsx    From next-right-now-admin with MIT License 6 votes vote down vote up
static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> {
    try {
      Sentry.addBreadcrumb({ // See https://docs.sentry.io/enriching-error-data/breadcrumbs
        category: fileLabel,
        message: `Preparing document (${isBrowser() ? 'browser' : 'server'})`,
        level: Sentry.Severity.Debug,
      });

      const initialProps: DocumentInitialProps = await Document.getInitialProps(ctx);
      const { req }: NextPageContext = ctx;
      const cookies: Cookies = NextCookies(ctx); // Parses Next.js cookies in a universal way (server + client)
      const lang: string = universalLanguageDetect({
        supportedLanguages: SUPPORTED_LANGUAGES, // Whitelist of supported languages, will be used to filter out languages that aren't supported
        fallbackLanguage: LANG_EN, // Fallback language in case the user's language cannot be resolved
        acceptLanguageHeader: get(req, 'headers.accept-language'), // Optional - Accept-language header will be used when resolving the language on the server side
        serverCookies: cookies, // Optional - Cookie "i18next" takes precedence over navigator configuration (ex: "i18next: fr"), will only be used on the server side
        errorHandler: (error: Error, level: ERROR_LEVELS, origin: string, context: object): void => {
          Sentry.withScope((scope): void => {
            scope.setExtra('level', level);
            scope.setExtra('origin', origin);
            scope.setContext('context', context);
            Sentry.captureException(error);
          });
          logger.error(error.message);
        },
      });

      return { ...initialProps, lang };
    } catch (e) {
      // If an error happens, log it and then try to render the page again with minimal processing
      // This way, it'll render something on the client. (otherwise, it'd completely crash the server and render "Internal Server Error" on the client)
      Sentry.captureException(e);

      const initialProps: DocumentInitialProps = await Document.getInitialProps(ctx);
      return { ...initialProps };
    }
  }
Example #19
Source File: [permalink].tsx    From NextJS-NestJS-GraphQL-Starter with MIT License 6 votes vote down vote up
function UserProfilePage(props: NextPageContext) {
  const { data, loading, error } = useUserQuery({
    variables: { input: { userPermalink: get(props, 'query.permalink', '') } }
  });

  const user = get(data, 'user', null);

  if ((!loading && !user) || error) {
    return <Error statusCode={404} />;
  }

  if (loading) {
    return <div>loading,..,s</div>;
  }

  return (
    <App
      title={loading ? '' : user.name}
      description=""
      breadcrumbs={[
        {
          label: user.name
        }
      ]}
    >
      <Box use="header">
        <Heading>{user.name}</Heading>
        <Text>{user.bio}</Text>
      </Box>
    </App>
  );
}
Example #20
Source File: addbot.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
getServerSideProps = async (ctx: NextPageContext) => {
	const parsed = parseCookie(ctx.req)
	const user = await get.Authorization(parsed?.token)
	return { props: { logged: !!user, user: await get.user.load(user || ''), csrfToken: getToken(ctx.req, ctx.res) } }
}
Example #21
Source File: with-instantsearch.tsx    From next-instantsearch with MIT License 5 votes vote down vote up
withInstantSearch = (options: WithInstantSearchOptions) => (
  WrappedComponent: NextComponentType | any
) => {
  const onSearchStateChange =
    options.onSearchStateChange || utils.onSearchStateChange;

  const InstantSearchApp = (props: any) => {
    const [searchState, setSearchState] = useState(props.searchState);
    const router = useRouter();
    const indexName = props.indexName || options.indexName;

    const handleSearchStateChange = (state: any) => {
      setSearchState(state);
      onSearchStateChange(state, router);
    };

    return (
      <InstantSearch
        {...props}
        indexName={indexName}
        searchState={searchState}
        searchClient={options.searchClient}
        createURL={utils.createURL}
        onSearchStateChange={handleSearchStateChange}
      >
        <WrappedComponent {...props} />
      </InstantSearch>
    );
  };

  InstantSearchApp.getInitialProps = async (ctx: NextPageContext) => {
    const { asPath = "" } = ctx;

    const getInitialProps = WrappedComponent.getInitialProps || (() => ({}));
    const pageProps: any = await getInitialProps(ctx);

    const indexName = pageProps.indexName || options.indexName;

    const searchStateFromPath = utils.pathToSearchState(asPath);
    const searchStateFromProps = pageProps.searchState || {};
    const searchState = merge(searchStateFromPath, searchStateFromProps);

    const InstantSearchSSR = (props: any) => {
      const component = () => <InstantSearchApp {...pageProps} {...props} />;

      return options.decorate
        ? options.decorate({ ctx, component })
        : component();
    };

    const resultsState = await findResultsState(InstantSearchSSR, {
      indexName,
      searchClient: options.searchClient,
      searchState,
    });

    return {
      ...pageProps,
      indexName,
      searchState,
      resultsState,
    };
  };

  return hoistNonReactStatics(InstantSearchApp, WrappedComponent, {
    getInitialProps: true,
  });
}
Example #22
Source File: _error.tsx    From frontend with MIT License 5 votes vote down vote up
CustomError.getInitialProps = async (ctx: NextPageContext) => {
  const { err, asPath } = ctx
  const errorInitialProps = await NextErrorComponent.getInitialProps(ctx)
  // Workaround for https://github.com/vercel/next.js/issues/8592, mark when
  // getInitialProps has run
  const updatedProps = {
    ...errorInitialProps,
    hasGetInitialPropsRun: true,
  }

  // Running on the server, the response object (`res`) is available.
  //
  // Next.js will pass an err on the server if a page's data fetching methods
  // threw or returned a Promise that rejected
  //
  // Running on the client (browser), Next.js will provide an err if:
  //
  //  - a page's `getInitialProps` threw or returned a Promise that rejected
  //  - an exception was thrown somewhere in the React lifecycle (render,
  //    componentDidMount, etc) that was caught by Next.js's React Error
  //    Boundary. Read more about what types of exceptions are caught by Error
  //    Boundaries: https://reactjs.org/docs/error-boundaries.html

  if (err) {
    Sentry.captureException(err)

    // Flushing before returning is necessary if deploying to Vercel, see
    // https://vercel.com/docs/platform/limits#streaming-responses
    await Sentry.flush(2000)

    return updatedProps
  }

  // If this point is reached, getInitialProps was called without any
  // information about what the error might be. This is unexpected and may
  // indicate a bug introduced in Next.js, so record it in Sentry
  Sentry.captureException(new Error(`_error.js getInitialProps missing data at path: ${asPath}`))
  await Sentry.flush(2000)

  return updatedProps
}
Example #23
Source File: 500.tsx    From frontend with MIT License 5 votes vote down vote up
export default function NotFound(ctx: NextPageContext) {
  return <NextError statusCode={ctx.err?.statusCode || 500} />
}
Example #24
Source File: _error.tsx    From nextclade with MIT License 5 votes vote down vote up
ErrorPage.getInitialProps = ({ res, err }: NextPageContext): Promise<ErrorPageProps> | ErrorPageProps => {
  const statusCode = res?.statusCode ?? err?.statusCode
  return { statusCode }
}
Example #25
Source File: panel.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
getServerSideProps = async (ctx: NextPageContext) => {
	const parsed = parseCookie(ctx.req)
	const user = await get.Authorization(parsed?.token) || ''
	const submits = await get.botSubmits.load(user)

	return { props: { logged: !!user, user:  await get.user.load(user), submits, csrfToken: getToken(ctx.req, ctx.res) } }
}
Example #26
Source File: index.tsx    From core with GNU Affero General Public License v3.0 5 votes vote down vote up
getServerSideProps = async (ctx: NextPageContext) => {
	const parsed = parseCookie(ctx.req)
	const user = await get.Authorization(parsed?.token) || ''

	return {
		props: { user: await get.user.load(user) }
	}
}
Example #27
Source File: _error.tsx    From next-right-now-admin with MIT License 5 votes vote down vote up
NRNError.getInitialProps = async (props: NextPageContext): Promise<ErrorProps> => {
  const { res, err, asPath } = props;
  // @ts-ignore
  const errorInitialProps: ErrorProps = await Error.getInitialProps({ res, err });

  // Workaround for https://github.com/zeit/next.js/issues/8592, mark when
  // getInitialProps has run
  errorInitialProps.isSSRReadyToRender = true;

  if (res) {
    // Running on the server, the response object is available.
    //
    // Next.js will pass an err on the server if a page's `getInitialProps`
    // threw or returned a Promise that rejected

    if (res.statusCode === 404) {
      // Opinionated: do not record an exception in Sentry for 404
      return { statusCode: 404, isSSRReadyToRender: true };
    }

    if (err) {
      Sentry.captureException(err);

      return errorInitialProps;
    }
  } else {
    // Running on the client (browser).
    //
    // Next.js will provide an err if:
    //
    //  - a page's `getInitialProps` threw or returned a Promise that rejected
    //  - an exception was thrown somewhere in the React lifecycle (render,
    //    componentDidMount, etc) that was caught by Next.js's React Error
    //    Boundary. Read more about what types of exceptions are caught by Error
    //    Boundaries: https://reactjs.org/docs/error-boundaries.html
    if (err) {
      Sentry.captureException(err);

      return errorInitialProps;
    }
  }

  // If this point is reached, getInitialProps was called without any
  // information about what the error might be. This is unexpected and may
  // indicate a bug introduced in Next.js, so record it in Sentry
  Sentry.captureException(
    // @ts-ignore
    new Error(`_error.js getInitialProps missing data at path: ${asPath}`),
  );

  return errorInitialProps;
};
Example #28
Source File: _app.tsx    From next-right-now-admin with MIT License 5 votes vote down vote up
/**
   * Initialise the application
   *
   * XXX Executed both on server and client side, but with different props (req, res are undefined on the client-side)
   *
   * @param props
   * @see https://github.com/zeit/next.js/#fetching-data-and-component-lifecycle
   */
  static async getInitialProps(props: AppInitialProps): Promise<AppRenderProps> {
    const { ctx }: AppInitialProps = props;
    const { req, res }: NextPageContext = ctx;
    const readonlyCookies: Cookies = NextCookies(ctx); // Parses Next.js cookies in a universal way (server + client)
    const cookiesManager: UniversalCookiesManager = new UniversalCookiesManager(req, res);
    const userSession: UserSemiPersistentSession = cookiesManager.getUserData();
    let publicHeaders: PublicHeaders = {};

    Sentry.configureScope((scope) => { // See https://www.npmjs.com/package/@sentry/node
      scope.setTag('userId', userSession.id);
      scope.setContext('userSession', userSession);
      scope.setContext('cookies', readonlyCookies);
    });

    Sentry.addBreadcrumb({ // See https://docs.sentry.io/enriching-error-data/breadcrumbs
      category: fileLabel,
      message: `Preparing app (${isBrowser() ? 'browser' : 'server'})`,
      level: Sentry.Severity.Debug,
    });

    if (req) {
      const { headers }: IncomingMessage = req;
      publicHeaders = {
        'accept-language': get(headers, 'accept-language'),
        'user-agent': get(headers, 'user-agent'),
        'host': get(headers, 'host'),
      };

      Sentry.configureScope((scope) => { // See https://www.npmjs.com/package/@sentry/node
        scope.setContext('headers', headers);
      });
    }

    // Resolves the lang, will first check in cookies, and then browser settings
    const lang: string = universalLanguageDetect({
      supportedLanguages: SUPPORTED_LANGUAGES, // Whitelist of supported languages, will be used to filter out languages that aren't supported
      fallbackLanguage: LANG_EN, // Fallback language in case the user's language cannot be resolved
      acceptLanguageHeader: get(req, 'headers.accept-language'), // Optional - Accept-language header will be used when resolving the language on the server side
      serverCookies: readonlyCookies, // Optional - Cookie "i18next" takes precedence over navigator configuration (ex: "i18next: fr"), will only be used on the server side
      errorHandler: (error: Error, level: ERROR_LEVELS, origin: string, context: object): void => {
        Sentry.withScope((scope): void => {
          scope.setExtra('level', level);
          scope.setExtra('origin', origin);
          scope.setContext('context', context);
          Sentry.captureException(error);
        });
        logger.error(error.message);
      },
    });

    // Calls page's `getInitialProps` and fills `appProps.pageProps` - XXX See https://nextjs.org/docs#custom-app
    const appProps: AppRenderProps = await NextApp.getInitialProps(props);

    Sentry.configureScope((scope) => { // See https://www.npmjs.com/package/@sentry/node
      scope.setExtra('lang', lang);
    });

    appProps.pageProps = {
      ...appProps.pageProps,
      headers: publicHeaders, // Publicly available headers - whitelist
      readonlyCookies,
      userSession,
      lang, // i.e: 'en'
      isSSRReadyToRender: true,
      isSSR: !!req,
    };

    return { ...appProps };
  }
Example #29
Source File: fetchPageData.ts    From next-page-tester with MIT License 4 votes vote down vote up
/*
 * fetchPageData behaves differently depending on whether custom /_app
 * fetches data or not (appInitialProps)
 *
 * /_app HAS NOT fetched data:
 * fetch page data using the first available method:
 * - getInitialProps
 * - getServerSideProps
 * - getStaticProps
 *
 * /_app HAS fetched data:
 * DO NOT call getInitialProps, if available
 * If available, call getServerSideProps or getServerSideProps
 * and merge returned object's prop property with appInitialProps.pageProps
 *
 * If no fetching methods available, return appInitialProps.pageProps as {props: appInitialProps.pageProp}
 */
export default async function fetchPageData({
  pageObject,
  appInitialProps,
  options,
}: {
  pageObject: PageObject;
  appInitialProps?: AppInitialProps;
  options: ExtendedOptions;
}): Promise<PageData> {
  const { env } = options;
  const { files } = pageObject;
  const pageFile = files[env].pageFile;
  ensureNoMultipleDataFetchingMethods({ page: pageFile });

  const pageComponent = pageFile.default;
  const { getInitialProps } = pageComponent;
  if (
    getInitialProps &&
    // getInitialProps is not called when custom App has the same method
    !appInitialProps
  ) {
    const ctx: NextPageContext = makeGetInitialPropsContext({
      options,
      pageObject,
    });

    if (env === RuntimeEnvironment.CLIENT) {
      const initialProps = await getInitialProps(ctx);
      return { props: initialProps };
    } else {
      const initialProps = await executeAsIfOnServer(() =>
        getInitialProps(ctx)
      );
      return { props: initialProps };
    }
  }

  // Data fetching methods available to actual pages only
  if (pageObject.type === 'found') {
    const { files, params } = pageObject;
    const serverPageFile = files.server.pageFile;
    if (serverPageFile.getServerSideProps) {
      const { getServerSideProps } = serverPageFile;
      const ctx: GetServerSidePropsContext<
        typeof params
      > = makeGetServerSidePropsContext({ options, pageObject });
      const pageData = await executeAsIfOnServer(() => getServerSideProps(ctx));
      ensurePageDataHasProps({ pageData });
      return mergePageDataWithAppData({ pageData, appInitialProps });
    }

    if (serverPageFile.getStaticProps) {
      const { getStaticProps } = serverPageFile;
      const ctx: GetStaticPropsContext<typeof params> = makeStaticPropsContext({
        pageObject,
      });
      // @TODO introduce `getStaticPaths` logic
      // https://nextjs.org/docs/basic-features/data-fetching#getstaticpaths-static-generation
      const pageData = await executeAsIfOnServer(() => getStaticProps(ctx));
      ensurePageDataHasProps({ pageData });
      return mergePageDataWithAppData({ pageData, appInitialProps });
    }

    if (appInitialProps) {
      const { pageProps, ...restOfAppInitialProps } = appInitialProps;
      return { props: pageProps, appProps: <PageProps>restOfAppInitialProps };
    }
  }

  return {};
}