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

docs(packages): Add TSDocs to all remaining packages #3079

Merged
merged 16 commits into from
Mar 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lucky-months-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@urql/core': patch
---

Add missing type exports of SSR-related types (`SerializedResult`, `SSRExchangeParams`, `SSRExchange`, and `SSRData`) to `@urql/core`'s type exports.
7 changes: 7 additions & 0 deletions .changeset/strong-shirts-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@urql/introspection': patch
'@urql/storage-rn': patch
'next-urql': patch
---

Add TSDocs to `@urql/*` packages.
8 changes: 8 additions & 0 deletions .changeset/tricky-cherries-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@urql/preact': patch
'@urql/svelte': patch
'urql': patch
'@urql/vue': patch
---

Add TSDocs to all `urql` bindings packages.
7 changes: 7 additions & 0 deletions packages/core/src/exchanges/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ export { dedupExchange } from './dedup';
export { fetchExchange } from './fetch';
export { composeExchanges } from './compose';

export type {
SerializedResult,
SSRExchangeParams,
SSRExchange,
SSRData,
} from './ssr';

export type {
SubscriptionOperation,
SubscriptionForwarder,
Expand Down
15 changes: 15 additions & 0 deletions packages/introspection/src/getIntrospectedSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ import {
getIntrospectionQuery,
} from 'graphql';

/** Returns an {@link IntrospectionQuery} result for a given GraphQL schema.
*
* @param input - A GraphQL schema, either as an SDL string, or a {@link GraphQLSchema} object.
* @returns an {@link IntrospectionQuery} result.
*
* @remarks
* `getIntrospectedSchema` can be used to get a Schema Introspection result from
* a given GraphQL schema. The schema can be passed as an SDL string or a
* {@link GraphQLSchema} object. If an {@link IntrospectionQuery} object is
* passed, it'll be passed through.
*
* @throws
* If `input` cannot be parsed or converted into a {@link GraphQLSchema} then
* a {@link TypeError} will be thrown.
*/
export const getIntrospectedSchema = (
input: string | IntrospectionQuery | GraphQLSchema
): IntrospectionQuery => {
Expand Down
44 changes: 39 additions & 5 deletions packages/introspection/src/minifyIntrospectionQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,52 @@ const minifyIntrospectionType = (
}
};

/** Input parameters for the {@link minifyIntrospectionQuery} function. */
export interface MinifySchemaOptions {
/** Includes scalar names (instead of an `Any` replacement) in the output when enabled. */
/** Includes scalars instead of removing them.
*
* @remarks
* By default, all scalars will be replaced by a single scalar called `Any`
* in the output, unless this option is set to `true`.
*/
includeScalars?: boolean;
/** Includes enums (instead of an `Any` replacement) in the output when enabled. */
/** Includes enums instead of removing them.
*
* @remarks
* By default, all enums will be replaced by a single scalar called `Any`
* in the output, unless this option is set to `true`.
*/
includeEnums?: boolean;
/** Includes all input objects (instead of an `Any` replacement) in the output when enabled. */
/** Includes inputs instead of removing them.
*
* @remarks
* By default, all inputs will be replaced by a single scalar called `Any`
* in the output, unless this option is set to `true`.
*/
includeInputs?: boolean;
/** Includes all directives in the output when enabled. */
/** Includes directives instead of removing them. */
includeDirectives?: boolean;
}

/** Removes extraneous information from introspected schema data to minify it and prepare it for use on the client-side. */
/** Minifies an {@link IntrospectionQuery} for use with Graphcache or the `populateExchange`.
*
* @param schema - An {@link IntrospectionQuery} object to be minified.
* @param opts - An optional {@link MinifySchemaOptions} configuration object.
* @returns the minified {@link IntrospectionQuery} object.
*
* @remarks
* `minifyIntrospectionQuery` reduces the size of an {@link IntrospectionQuery} by
* removing data and information that a client-side consumer, like Graphcache or the
* `populateExchange`, may not require.
*
* At the very least, it will remove system types, descriptions, depreactions,
* and source locations. Unless disabled via the options passed, it will also
* by default remove all scalars, enums, inputs, and directives.
*
* @throws
* If `schema` receives an object that isn’t an {@link IntrospectionQuery}, a
* {@link TypeError} will be thrown.
*/
export const minifyIntrospectionQuery = (
schema: IntrospectionQuery,
opts: MinifySchemaOptions = {}
Expand Down
26 changes: 25 additions & 1 deletion packages/next-urql/src/init-urql-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,38 @@ import { Client, ClientOptions, createClient } from '@urql/core';

let urqlClient: Client | null = null;

/** Resets the `Client` that {@link initUrqlClient} returns.
*
* @remarks
* `resetClient` will force {@link initUrqlClient} to create a new
* {@link Client}, rather than reusing the same `Client` it already
* created on the client-side.
*
* This may be used to force the cache and any state in the `Client`
* to be cleared and reset.
*/
export function resetClient() {
urqlClient = null;
}

/** Creates a {@link Client} the given options.
*
* @param clientOptions - {@link ClientOptions} to create the `Client` with.
* @param canEnableSuspense - Enables React Suspense on the server-side for `react-ssr-prepass`.
* @returns the created {@link Client}
*
* @remarks
* `initUrqlClient` creates a {@link Client} with the given options,
* like {@link createClient} does, but reuses the same client when
* run on the client-side.
*
* As long as `canEnableSuspense` is set to `true`, it enables React Suspense
* mode on the server-side for `react-ssr-prepass`.
*/
export function initUrqlClient(
clientOptions: ClientOptions,
canEnableSuspense: boolean
): Client | null {
): Client {
// Create a new Client for every server-side rendered request.
// This ensures we reset the state for each rendered page.
// If there is an exising client instance on the client-side, use it.
Expand Down
108 changes: 76 additions & 32 deletions packages/next-urql/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,102 @@
import { GraphQLError } from 'graphql';
import { ClientOptions, Exchange, Client } from 'urql';
import { NextPageContext } from 'next';
import { AppContext } from 'next/app';
import type { ClientOptions, Client, SSRExchange, SSRData } from '@urql/core';
import type { NextPageContext } from 'next';
import type { AppContext } from 'next/app';

/** The Next.js {@link NextPageContext}, as modified by `next-urql`. */
export interface NextUrqlPageContext extends NextPageContext {
urqlClient: Client;
}

/** The Next.js {@link AppContext}, as modified by `next-urql`. */
export interface NextUrqlAppContext extends AppContext {
urqlClient: Client;
}

export type NextUrqlContext = NextUrqlPageContext | NextUrqlAppContext;

/** Passed to {@link withUrqlClient} returning the options a {@link Client} is created with.
*
* @param ssrExchange - the `ssrExchange` you must use in your `exchanges` array.
* @param ctx - Passed when `getInitialProps` is used and set to Next.js’ {@link NextPageContext}.
* @returns a {@link ClientOptions} configuration object to create a {@link Client} with.
*
* @remarks
* You must define a `getClientConfig` function and pass it to {@link withUrqlClient}.
*
* This function defines the options passed to {@link initUrqlClient}.
* It passes you an `ssrExchange` that you must use in your `exchanges` array.
*
* @example
* ```ts
* import { cacheExchange, fetchExchange } from '@urql/core';
* import { withUrqlClient } from 'next-urql';
*
* const WrappedPage = withUrqlClient(
* (ssrExchange) => ({
* url: 'https://YOUR_API',
* exchanges: [cacheExchange, ssrExchange, fetchExchange],
* })
* )(Page);
* ```
*/
export type NextUrqlClientConfig = (
ssrExchange: SSRExchange,
ctx?: NextPageContext
) => ClientOptions;

export interface WithUrqlState {
urqlState?: SSRData;
}

export interface WithUrqlClient {
/** Props that {@link withUrqlClient} components pass on to your component. */
export interface WithUrqlProps {
/** The {@link Client} that {@link withUrqlClient} created for your component. */
urqlClient?: Client;
}

export interface WithUrqlProps extends WithUrqlClient, WithUrqlState {
resetUrqlClient?: () => void;
/** Next.js’ `pageProps` prop, as passed to it by Next.js. */
pageProps: any;
/** The SSR data that {@link withUrqlClient} created for your component. */
urqlState?: SSRData;
/** Resets the `Client` that on the client-side.
*
* @remarks
* `resetUrqlClient` will force a new {@link Client} to be created
* on the client-side, rather than the same `Client` with the same
* server-side data to be reused.
*
* This may be used to force the cache and any state in the `Client`
* to be cleared and reset.
*/
resetUrqlClient?(): void;
[key: string]: any;
}

export interface SerializedResult {
data?: any;
error?: {
graphQLErrors: Array<Partial<GraphQLError> | string>;
networkError?: string;
};
}

export interface SSRData {
[key: string]: SerializedResult;
}

export interface SSRExchange extends Exchange {
/** Rehydrates cached data */
restoreData(data: SSRData): void;
/** Extracts cached data */
extractData(): SSRData;
}

/** Options that may be passed to the {@link withUrqlClient} wrapper function. */
export interface WithUrqlClientOptions {
/** Enables automatic server-side rendering mode.
*
* @remarks
* When enabled, {@link withUrqlClient} will add a `getInitialProps`
* function to the resulting component, even if you haven't defined
* one.
*
* This function will automatically capture `urql`'s SSR state on the
* server-side and rehydrate it on the client-side, unless
* {@link WithUrqlClientOptions.neverSuspend} is `true`.
*/
ssr?: boolean;
/** Disables automatic server-side rendering, even if a `getInitialProps` function is defined.
*
* @remarks
* When enabled, {@link withUrqlClient} will never execute queries
* on the server-side automatically, and will instead rely on you
* to do so manually.
*/
neverSuspend?: boolean;
/** Enables reexecuting operations on the client-side after rehydration.
*
* @remarks
* When enabled, `staleWhileRevalidate` will reexecute GraphQL queries on
* the client-side, if they’ve been rehydrated from SSR state.
*
* This is useful if you, for instance, cache your server-side rendered
* pages, or if you use `getStaticProps` and wish to get this data
* updated.
*/
staleWhileRevalidate?: boolean;
}
57 changes: 40 additions & 17 deletions packages/next-urql/src/with-urql-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,66 @@ import {
ReactNode,
ReactElement,
} from 'react';
import ssrPrepass from 'react-ssr-prepass';
import { NextComponentType, NextPage, NextPageContext } from 'next';
import NextApp, { AppContext } from 'next/app';

import {
Provider,
SSRExchange,
ssrExchange,
dedupExchange,
cacheExchange,
fetchExchange,
} from 'urql';

import ssrPrepass from 'react-ssr-prepass';
import { NextComponentType, NextPage, NextPageContext } from 'next';
import NextApp, { AppContext } from 'next/app';

import { initUrqlClient, resetClient } from './init-urql-client';

import {
NextUrqlClientConfig,
NextUrqlContext,
WithUrqlProps,
WithUrqlClientOptions,
SSRExchange,
} from './types';

let ssr: SSRExchange;
type NextPageWithLayout = NextPage & {
getLayout?: (page: ReactElement) => ReactNode;
};

/** Creates a wrapper for Next.js Page, App, or Document components that rehydrates `urql` state.
*
* @param getClientConfig - function used to create the {@link Client}
* @param options - optional {@link WithUrqlClientOptions} configuration options
* @returns a higher-order component function, which you can pass a Next.js page or app component.
*
* @remarks
* Used to wrap a Next.js page or app component. It will create a {@link Client} and passes
* it on to the child component and adds a React Provider for it.
*
* It will restore any page’s `pageProps.urqlState` with the {@link SSRExchange} and also
* supports doing this automatically when the {@link WithUrqlClientOptions.ssr} option
* is enabled.
*
* If you don’t define the above option, you will have to write `getServerSideProps` or
* `getStaticProps` methods on your component manually.
*
* @see {@link https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs} for more documentation.
*
* @example
* ```ts
* import { cacheExchange, fetchExchange } from '@urql/core';
* import { withUrqlClient } from 'next-urql';
*
* const WrappedPage = withUrqlClient(
* (ssrExchange) => ({
* url: 'https://YOUR_API',
* exchanges: [cacheExchange, ssrExchange, fetchExchange],
* }),
* { ssr: true },
* )(Page);
* ```
*/
export function withUrqlClient(
getClientConfig: NextUrqlClientConfig,
options?: WithUrqlClientOptions
Expand Down Expand Up @@ -77,12 +110,7 @@ export function withUrqlClient(
const clientConfig = getClientConfig(ssr);
if (!clientConfig.exchanges) {
// When the user does not provide exchanges we make the default assumption.
clientConfig.exchanges = [
dedupExchange,
cacheExchange,
ssr,
fetchExchange,
];
clientConfig.exchanges = [cacheExchange, ssr, fetchExchange];
}

return initUrqlClient(clientConfig, shouldEnableSuspense)!;
Expand Down Expand Up @@ -129,12 +157,7 @@ export function withUrqlClient(
const clientConfig = getClientConfig(ssrCache, ctx);
if (!clientConfig.exchanges) {
// When the user does not provide exchanges we make the default assumption.
clientConfig.exchanges = [
dedupExchange,
cacheExchange,
ssrCache,
fetchExchange,
];
clientConfig.exchanges = [cacheExchange, ssrCache, fetchExchange];
}

const urqlClient = initUrqlClient(clientConfig, !options!.neverSuspend);
Expand Down
Loading