Skip to content

Commit

Permalink
fix: addresses a number of typing issues
Browse files Browse the repository at this point in the history
  • Loading branch information
platypusrex committed Sep 24, 2022
1 parent 63cb37c commit fc5e605
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 62 deletions.
18 changes: 8 additions & 10 deletions example/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NextPage } from 'next';
import type { InferGetServerSidePropsType, NextPage } from 'next';
import Head from 'next/head';
import Image from 'next/image';
import Link from 'next/link';
Expand All @@ -15,11 +15,8 @@ import {
UsersQuery
} from '../types/generated';

interface HomeProps {
users?: UserFragment[] | null;
}

const Home: NextPage<HomeProps> = () => {
const Home: NextPage<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ users }) => {
console.log('users from server side hydration', users);
const { data } = useQuery<UsersQuery, UserQueryVariables>(USERS_QUERY);

return (
Expand Down Expand Up @@ -67,7 +64,7 @@ const Home: NextPage<HomeProps> = () => {
)
}

export const getServerSideProps = getServerSideApolloProps<HomeProps>({
export const getServerSideProps = getServerSideApolloProps<{ users?: UserFragment[] | null }>({
hydrateQueries: ['users'],
onClientInitialized: async (ctx, apolloClient) => {
if (ctx.query.addUser) {
Expand All @@ -94,10 +91,11 @@ export const getServerSideProps = getServerSideApolloProps<HomeProps>({
}
return { props: {} };
},
onHydrationComplete: ({ results }) => {
const users = results?.users?.data.users ?? null;
onHydrationComplete: ({ users }) => {
return {
props: { users },
props: {
users: users?.data.users ?? null
},
};
},
});
Expand Down
14 changes: 5 additions & 9 deletions example/src/pages/profile/[userId].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NextPage } from 'next';
import type { InferGetServerSidePropsType, NextPage } from 'next';
import Head from 'next/head';
import Image from 'next/image';
import Link from 'next/link';
Expand All @@ -8,11 +8,7 @@ import { BOOKS_QUERY, USER_QUERY } from '../../gql';
import { BooksQuery, UserQuery, UserQueryVariables } from '../../types/generated';
import styles from '../../styles/Home.module.css';

interface ProfilePageProps {
userId: string;
}

const ProfilePage: NextPage<ProfilePageProps> = ({ userId }) => {
const ProfilePage: NextPage<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ userId }) => {
const { data: userData } = useQuery<UserQuery, UserQueryVariables>(USER_QUERY, {
variables: { id: userId }
});
Expand Down Expand Up @@ -86,10 +82,10 @@ const ProfilePage: NextPage<ProfilePageProps> = ({ userId }) => {
)
}

export const getServerSideProps = getServerSideApolloProps<ProfilePageProps>({
export const getServerSideProps = getServerSideApolloProps<{ userId: string }>({
hydrateQueries: ['user', 'books'],
onHydrationComplete: ({ results }) => {
const user = results?.user?.data.user;
onHydrationComplete: ({ user: userResult }) => {
const user = userResult?.data.user;

if (!user) {
return {
Expand Down
25 changes: 12 additions & 13 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1321,9 +1321,9 @@
integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==

"@types/node@*":
version "18.7.18"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154"
integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==
version "18.7.19"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.19.tgz#ad83aa9b7af470fab7e0f562be87e97dc8ffe08e"
integrity sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==

"@types/node@17.0.25":
version "17.0.25"
Expand Down Expand Up @@ -2293,9 +2293,9 @@ ecdsa-sig-formatter@1.0.11:
safe-buffer "^5.0.1"

electron-to-chromium@^1.4.251:
version "1.4.258"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.258.tgz#44c5456f487be082f038282fbcfd7b06ae99720d"
integrity sha512-vutF4q0dTUXoAFI7Vbtdwen/BJVwPgj8GRg/SElOodfH7VTX+svUe62A5BG41QRQGk5HsZPB0M++KH1lAlOt0A==
version "1.4.260"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.260.tgz#9aa3348d037686b47ccc5d3b48fe417b1f20017a"
integrity sha512-1GxPM2Bdz1AjuNjho9/TqJfxM7KZ7R8s4vA5cbbIoVacQXfvZlV+d7Y1lu4BhGzEBfjjhakr3NXKqN0PxPXIsg==

emoji-regex@^8.0.0:
version "8.0.0"
Expand Down Expand Up @@ -3116,9 +3116,9 @@ is-boolean-object@^1.1.0:
has-tostringtag "^1.0.0"

is-callable@^1.1.4, is-callable@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44"
integrity sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==
version "1.2.7"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==

is-core-module@^2.7.0, is-core-module@^2.9.0:
version "2.10.0"
Expand Down Expand Up @@ -3678,10 +3678,9 @@ next@12.1.5:
"@next/swc-win32-ia32-msvc" "12.1.5"
"@next/swc-win32-x64-msvc" "12.1.5"

nextjs-apollo-client@latest:
version "0.2.2"
resolved "https://registry.yarnpkg.com/nextjs-apollo-client/-/nextjs-apollo-client-0.2.2.tgz#de2e31b892561caab932a8daf0403d6738d9ed89"
integrity sha512-kW9MJMSuI6dr6M8M9MC9GVzmFWP4FJS617OJK2YHyo4QTAp3Pcg5buHw2EE00AqfhgHqKuoJo9cDmHJFl63Egw==
"nextjs-apollo-client@file:../nextjs-apollo-client-0.3.0-alpha.0.tgz":
version "0.3.0-alpha.0"
resolved "file:../nextjs-apollo-client-0.3.0-alpha.0.tgz#f6002d54d46d9cc42d05a7fd0fe2ca578558073a"
dependencies:
deepmerge "^4.2.2"
lodash-es "^4.17.21"
Expand Down
19 changes: 8 additions & 11 deletions src/NextApolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ApolloClientConfig,
GetServerSideApolloProps,
GetServerSideApolloPropsOptions,
HydrationCompleteResults,
HydrationResponse,
InitializeApolloArgs,
PartialApolloClientOptions,
Expand All @@ -28,7 +29,7 @@ export interface NextApolloClientOptions {
hydrationMap?: QueryHydrationMap;
}

export class NextApolloClient<THydrationMap extends QueryHydrationMap> {
export class NextApolloClient<THydrationMap extends QueryHydrationMap = any> {
private readonly _client!: NextApolloClientOptions['client'];
private readonly _hydrationMap?: NextApolloClientOptions['hydrationMap'];

Expand Down Expand Up @@ -121,12 +122,12 @@ export class NextApolloClient<THydrationMap extends QueryHydrationMap> {
onClientInitialized,
onHydrationComplete,
}: GetServerSideApolloPropsOptions<
TProps,
THydrationMap,
(keyof THydrationMap)[],
THydrationMap
> = {}): GetServerSideProps => async (
TProps
> = {}): GetServerSideProps<GetServerSideApolloProps & TProps> => async (
ctx: GetServerSidePropsContext
): Promise<GetServerSidePropsResult<GetServerSideApolloProps>> => {
): Promise<GetServerSidePropsResult<GetServerSideApolloProps & TProps>> => {
const apolloClient = this.initializeApollo({ headers: ctx.req.headers });
let baseProps = {};

Expand Down Expand Up @@ -159,15 +160,11 @@ export class NextApolloClient<THydrationMap extends QueryHydrationMap> {
}
if (curr.status === 'fulfilled') {
const currentKey = Object.keys(curr.value.data)[0];
// @ts-ignore
acc['results'] = {
...acc['results'],
[currentKey]: curr.value,
};
acc = { ...acc, [currentKey]: curr.value };
}
return acc;
},
{}
{} as HydrationCompleteResults<THydrationMap>
);

if (onHydrationComplete) {
Expand Down
27 changes: 20 additions & 7 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,31 @@ type ApolloClientFn = (
export type ApolloClientConfig = PartialApolloClientOptions | ApolloClientFn;

// getServerSideProps types
export type HydrationResponse<THydrationMap extends QueryHydrationMap = any> = {
export type HydrationResponse<THydrationMap extends QueryHydrationMap> = HydrationCompleteResults<
THydrationMap
> & {
errors?: ApolloError[];
results?: THydrationMap extends any ? AnyHydrationResults : HydrationResults<THydrationMap>;
};

export type HydrationCompleteResults<
THydrationMap extends QueryHydrationMap
> = THydrationMap extends never ? AnyHydrationResults : HydrationResults<THydrationMap>;

export type HydrateQueries<THydrationMap> =
| THydrationMap
| PureQueryOptions[]
| ((ctx: GetServerSidePropsContext) => PureQueryOptions[]);

export type ServerSidePropsResult<TProps> =
export type ServerSidePropsResult<TProps = Record<string, any>> =
| void
| Promise<void>
| Promise<GetServerSidePropsResult<TProps>>
| GetServerSidePropsResult<TProps>;

export interface GetServerSideApolloPropsOptions<
TProps = Record<string, any> & GetServerSideApolloProps,
THydrationMap extends QueryHydrationMap,
THydrationMapKeys = any,
THydrationMap extends QueryHydrationMap = any
TProps = Record<string, any>
> {
hydrateQueries?: HydrateQueries<THydrationMapKeys>;
onClientInitialized?: (
Expand All @@ -77,11 +82,19 @@ export interface GetServerSideApolloProps {
export type QueryHydrationMap = Record<string, (ctx: GetServerSidePropsContext) => QueryOptions>;

export type HydrationResults<T extends QueryHydrationMap> = {
[K in keyof T]?: ApolloQueryResult<HydrationQueryOptions<ReturnType<T[K]>>>;
[K in keyof T]?: ApolloQueryResult<
ReturnType<T[K]> extends QueryOptions ? HydrationQueryOptions<ReturnType<T[K]>> : any
>;
};

export type AnyHydrationResults<T = { [key: string]: any }> = {
[K in keyof T]?: ApolloQueryResult<T>;
};

export type HydrationQueryOptions<T> = T extends QueryOptions<any, infer Q> ? Q : never;
export type HydrationQueryOptions<T> = T extends QueryOptions<any, infer Q>
? StrictlyUnknown<Q> extends true
? any
: Q
: never;

type StrictlyUnknown<T> = unknown extends T ? true : false;
19 changes: 9 additions & 10 deletions test/getServerSideProps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,10 @@ describe('getServerSideApolloProps', () => {
client: () => apolloClient,
});

const onHydrationComplete: GetServerSideApolloPropsOptions<
any
>['onHydrationComplete'] = jest.fn(({ results }) => {
const users = results?.users?.data?.users;
return { props: { users } };
const onHydrationComplete: GetServerSideApolloPropsOptions<{
users: any;
}>['onHydrationComplete'] = jest.fn(({ users }) => {
return { props: { users: users?.data.users } };
});
const result = await getServerSideApolloProps({
hydrateQueries: [{ query: USERS_QUERY }],
Expand All @@ -127,7 +126,7 @@ describe('getServerSideApolloProps', () => {

expect(spy).toHaveBeenCalledWith({ query: USERS_QUERY });
expect(onHydrationComplete).toHaveBeenCalledWith({
results: { users: { data: { users: [] }, loading: false, networkStatus: 7 } },
users: { data: { users: [] }, loading: false, networkStatus: 7 },
});
expect(result).toEqual({
props: {
Expand All @@ -147,8 +146,8 @@ describe('getServerSideApolloProps', () => {

const onHydrationComplete: GetServerSideApolloPropsOptions<
any
>['onHydrationComplete'] = jest.fn(({ results }) => {
const users = results?.books?.data.books;
>['onHydrationComplete'] = jest.fn(({ books }) => {
const users = books?.data.books;
return !users ? { redirect: { destination: '/', permanent: false } } : { props: { users } };
});
const result = await getServerSideApolloProps({
Expand All @@ -173,8 +172,8 @@ describe('getServerSideApolloProps', () => {

const onHydrationComplete: GetServerSideApolloPropsOptions<
any
>['onHydrationComplete'] = jest.fn(({ results }) => {
const users = results?.books?.data.books;
>['onHydrationComplete'] = jest.fn(({ books }) => {
const users = books?.data.books;
return !users ? { notFound: true } : { props: { users } };
});
const result = await getServerSideApolloProps({
Expand Down
20 changes: 18 additions & 2 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { gql } from '@apollo/client';
import { gql, OperationVariables, QueryOptions } from '@apollo/client';
import { createMockClient } from '@apollo/client/testing';
import { generateHydrationMap } from '../../src';

Expand Down Expand Up @@ -26,4 +26,20 @@ export const context = {
req: { headers: {} },
};

export const hydrationMap = generateHydrationMap({ users: () => ({ query: USERS_QUERY }) });
export type UsersQuery = {
__typename?: 'Query';
users: Array<{
__typename?: 'User';
id: string;
firstName: string;
lastName: string;
username: string;
email: string;
phone?: string | null;
img: string;
}>;
};

export const hydrationMap = generateHydrationMap({
users: (): QueryOptions<OperationVariables, UsersQuery> => ({ query: USERS_QUERY }),
});

0 comments on commit fc5e605

Please sign in to comment.