Skip to content

Commit

Permalink
simplified and improved conditional types for custom endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Wire committed Dec 18, 2024
1 parent 4f8e7a9 commit 93b5136
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 178 deletions.
72 changes: 12 additions & 60 deletions packages/adapter-nextjs/src/api/generateServerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,14 @@ import { NextServer } from '../types';

import { createServerRunnerForAPI } from './createServerRunnerForAPI';

type CookiesClientParams<
WithEndpoint extends boolean,
WithApiKey extends boolean,
> = {
interface CookiesClientParams {
cookies: NextServer.ServerComponentContext['cookies'];
config: NextServer.CreateServerRunnerInput['config'];
} & CommonPublicClientOptions<WithEndpoint, WithApiKey>;
}

type ReqClientParams<
WithEndpoint extends boolean,
WithApiKey extends boolean,
> = {
interface ReqClientParams {
config: NextServer.CreateServerRunnerInput['config'];
} & CommonPublicClientOptions<WithEndpoint, WithApiKey>;

// NOTE: The type narrowing on CommonPublicClientOptions seems to hinge on
// defining these signatures separately. Not sure why offhand. This is worth
// some investigation later.
}

/**
* Generates an API client that can be used inside a Next.js Server Component with Dynamic Rendering
Expand All @@ -48,29 +38,9 @@ type ReqClientParams<
*/
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
>(
options: CookiesClientParams<false, false>,
): V6ClientSSRCookies<T, false, false>;
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
>(
options: CookiesClientParams<false, true>,
): V6ClientSSRCookies<T, false, true>;
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
>(
options: CookiesClientParams<true, false>,
): V6ClientSSRCookies<T, true, false>;
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
>(options: CookiesClientParams<true, true>): V6ClientSSRCookies<T, true, true>;
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
>(
options: CookiesClientParams<WithCustomEndpoint, WithApiKey>,
): V6ClientSSRCookies<T, WithCustomEndpoint, WithApiKey> {
Options extends CommonPublicClientOptions &
CookiesClientParams = CookiesClientParams,
>(options: Options): V6ClientSSRCookies<T, Options> {
if (typeof options.cookies !== 'function') {
throw new AmplifyServerContextError({
message:
Expand All @@ -96,10 +66,7 @@ export function generateServerClientUsingCookies<

const { cookies: _cookies, config: _config, ...params } = options;

return generateClientWithAmplifyInstance<
T,
V6ClientSSRCookies<T, WithCustomEndpoint, WithApiKey>
>({
return generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T, Options>>({
amplify: getAmplify,
config: resourcesConfig,
...params,
Expand All @@ -124,29 +91,14 @@ export function generateServerClientUsingCookies<
*/
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
>(options: ReqClientParams<false, false>): V6ClientSSRRequest<T, false, false>;
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
>(options: ReqClientParams<false, true>): V6ClientSSRRequest<T, false, true>;
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
>(options: ReqClientParams<true, false>): V6ClientSSRRequest<T, true, false>;
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
>(options: ReqClientParams<true, true>): V6ClientSSRRequest<T, true, true>;
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
>(
options: ReqClientParams<WithCustomEndpoint, WithApiKey>,
): V6ClientSSRRequest<T, WithCustomEndpoint, WithApiKey> {
Options extends CommonPublicClientOptions & ReqClientParams = ReqClientParams,
>(options: Options): V6ClientSSRRequest<T, Options> {
const amplifyConfig = parseAmplifyConfig(options.config);

const { config: _config, ...params } = options;

return generateClient<T, WithCustomEndpoint, WithApiKey>({
return generateClient<T>({
config: amplifyConfig,
...params,
} as any); // TS can't narrow the type here.
}) as any;
}
9 changes: 3 additions & 6 deletions packages/api-graphql/src/internals/generateClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import { isApiGraphQLConfig } from './utils/runtimeTypeGuards/isApiGraphQLProviderConfig';
import { isConfigureEventWithResourceConfig } from './utils/runtimeTypeGuards/isConfigureEventWithResourceConfig';
import { cancel, graphql, isCancelError } from './v6';
import { ClientGenerationParams } from './types';
import { ClientGenerationParams, CommonPublicClientOptions } from './types';

/**
* @private
Expand All @@ -37,11 +37,8 @@ import { ClientGenerationParams } from './types';
*/
export function generateClient<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
>(
params: ClientGenerationParams<WithCustomEndpoint, WithApiKey>,
): V6Client<T, WithCustomEndpoint, WithApiKey> {
Options extends CommonPublicClientOptions = object,
>(params: ClientGenerationParams): V6Client<T, Options> {
const client = {
[__amplify]: params.amplify,
[__authMode]: params.authMode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ import { cancel, graphql, isCancelError } from '..';
export function generateClientWithAmplifyInstance<
T extends Record<any, any> = never,
ClientType extends
| V6ClientSSRRequest<T, any, any>
| V6ClientSSRCookies<T, any, any> = V6ClientSSRCookies<T, any, any>,
| V6ClientSSRRequest<T>
| V6ClientSSRCookies<T> = V6ClientSSRCookies<T>,
>(
params: ServerClientGenerationParams & CommonPublicClientOptions<any, any>,
params: ServerClientGenerationParams & CommonPublicClientOptions,
): ClientType {
const client = {
[__amplify]: params.amplify,
Expand Down
54 changes: 20 additions & 34 deletions packages/api-graphql/src/internals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,32 @@ import { CustomHeaders } from '@aws-amplify/data-schema/runtime';
*
* The knobs available for configuring `generateClient` internally.
*/
export type ClientGenerationParams<
WithCustomEndpoint extends boolean,
WithApiKey extends boolean,
> = {
export type ClientGenerationParams = {
amplify: AmplifyClassV6;
} & CommonPublicClientOptions<WithCustomEndpoint, WithApiKey>;
} & CommonPublicClientOptions;

/**
* Common options that can be used on public `generateClient()` interfaces.
*/
export type CommonPublicClientOptions<
WithCustomEndpoint extends boolean,
WithApiKey extends boolean,
> = WithCustomEndpoint extends true
? WithApiKey extends true
?
| {
endpoint: string;
authMode: 'apiKey';
apiKey: string;
authToken?: string;
headers?: CustomHeaders;
}
| {
endpoint: string;
apiKey: string;
authMode: Exclude<GraphQLAuthMode, 'apiKey'>;
authToken?: string;
headers?: CustomHeaders;
}
: {
endpoint: string;
authMode: Exclude<GraphQLAuthMode, 'apiKey'>;
apiKey?: never;
authToken?: string;
headers?: CustomHeaders;
}
: {
export type CommonPublicClientOptions =
| {
endpoint?: never;
authMode?: GraphQLAuthMode;
authToken?: string;
apiKey?: string;
headers?: CustomHeaders;
};
}
| {
endpoint: string;
authMode: 'apiKey';
apiKey: string;
authToken?: string;
headers?: CustomHeaders;
}
| {
endpoint: string;
authMode: Exclude<GraphQLAuthMode, 'apiKey'>;
apiKey?: string;
authToken?: string;
headers?: CustomHeaders;
};
6 changes: 4 additions & 2 deletions packages/api-graphql/src/internals/v6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CustomHeaders } from '@aws-amplify/data-schema/runtime';

import { GraphQLAPI } from '../GraphQLAPI';
import {
CommonPublicClientOptions,
GraphQLOptionsV6,
GraphQLResponseV6,
V6Client,
Expand Down Expand Up @@ -97,9 +98,10 @@ import {
export function graphql<
FALLBACK_TYPES = unknown,
TYPED_GQL_STRING extends string = string,
Options extends CommonPublicClientOptions = object,
>(
this: V6Client,
options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,
options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING, Options>,
additionalHeaders?: CustomHeaders,
): GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING> {
// inject client-level auth
Expand Down Expand Up @@ -154,7 +156,7 @@ export function graphql<
{
...options,
endpoint: clientEndpoint,
},
} as any,
headers,
);

Expand Down
23 changes: 6 additions & 17 deletions packages/api-graphql/src/server/generateClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
AmplifyServer,
getAmplifyServerContext,
} from '@aws-amplify/core/internals/adapter-core';
import { ResourcesConfig } from '@aws-amplify/core';
import { CustomHeaders } from '@aws-amplify/data-schema/runtime';

import { generateClientWithAmplifyInstance } from '../internals/server';
Expand Down Expand Up @@ -35,26 +36,17 @@ import {
*/
export function generateClient<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
>(
options: GenerateServerClientParams<WithCustomEndpoint, WithApiKey>,
): V6ClientSSRRequest<T, WithCustomEndpoint, WithApiKey> {
Options extends GenerateServerClientParams = { config: ResourcesConfig },
>(options: Options): V6ClientSSRRequest<T, Options> {
// passing `null` instance because each (future model) method must retrieve a valid instance
// from server context
const client = generateClientWithAmplifyInstance<
T,
V6ClientSSRRequest<T, any, any>
>({
const client = generateClientWithAmplifyInstance<T, V6ClientSSRRequest<T>>({
amplify: null,
...options,
});

// TODO: improve this and the next type
const prevGraphql = client.graphql as unknown as GraphQLMethod<
WithCustomEndpoint,
WithApiKey
>;
const prevGraphql = client.graphql as unknown as GraphQLMethod<Options>;

const wrappedGraphql = (
contextSpec: AmplifyServer.ContextSpec,
Expand All @@ -70,10 +62,7 @@ export function generateClient<
);
};

client.graphql = wrappedGraphql as unknown as GraphQLMethodSSR<
WithCustomEndpoint,
WithApiKey
>;
client.graphql = wrappedGraphql as unknown as GraphQLMethodSSR<Options>;

return client;
}
59 changes: 21 additions & 38 deletions packages/api-graphql/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,9 @@ export type GraphQLOperation = Source | string;
export type GraphQLOptionsV6<
FALLBACK_TYPES = unknown,
TYPED_GQL_STRING extends string = string,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false, // i.e., The client already has apiKey configured.
> = WithCustomEndpoint extends true
? WithApiKey extends true
Options extends CommonPublicClientOptions = object,
> = Options['endpoint'] extends string
? Options['apiKey'] extends string
? {
query: TYPED_GQL_STRING | DocumentNode;
variables?: GraphQLVariablesV6<FALLBACK_TYPES, TYPED_GQL_STRING>;
Expand Down Expand Up @@ -447,58 +446,45 @@ export type ClientWithModels =

export type V6Client<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
Options extends CommonPublicClientOptions = object,
> = {
graphql: GraphQLMethod<WithCustomEndpoint, WithApiKey>;
graphql: GraphQLMethod<Options>;
cancel(promise: Promise<any>, message?: string): boolean;
isCancelError(error: any): boolean;
} & ClientExtensions<T>;

export type V6ClientSSRRequest<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
Options extends CommonPublicClientOptions = object,
> = {
graphql: GraphQLMethodSSR<WithCustomEndpoint, WithApiKey>;
graphql: GraphQLMethodSSR<Options>;
cancel(promise: Promise<any>, message?: string): boolean;
isCancelError(error: any): boolean;
} & ClientExtensionsSSRRequest<T>;

export type V6ClientSSRCookies<
T extends Record<any, any> = never,
WithCustomEndpoint extends boolean = false,
WithApiKey extends boolean = false,
Options extends CommonPublicClientOptions = object,
> = {
graphql: GraphQLMethod<WithCustomEndpoint, WithApiKey>;
graphql: GraphQLMethod<Options>;
cancel(promise: Promise<any>, message?: string): boolean;
isCancelError(error: any): boolean;
} & ClientExtensionsSSRCookies<T>;

export type GraphQLMethod<
WithCustomEndpoint extends boolean,
WithApiKey extends boolean,
> = <FALLBACK_TYPES = unknown, TYPED_GQL_STRING extends string = string>(
options: GraphQLOptionsV6<
FALLBACK_TYPES,
TYPED_GQL_STRING,
WithCustomEndpoint,
WithApiKey
>,
export type GraphQLMethod<Options extends CommonPublicClientOptions> = <
FALLBACK_TYPES = unknown,
TYPED_GQL_STRING extends string = string,
>(
options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING, Options>,
additionalHeaders?: CustomHeaders | undefined,
) => GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING>;

export type GraphQLMethodSSR<
WithCustomEndpoint extends boolean,
WithApiKey extends boolean,
> = <FALLBACK_TYPES = unknown, TYPED_GQL_STRING extends string = string>(
export type GraphQLMethodSSR<Options extends CommonPublicClientOptions> = <
FALLBACK_TYPES = unknown,
TYPED_GQL_STRING extends string = string,
>(
contextSpec: AmplifyServer.ContextSpec,
options: GraphQLOptionsV6<
FALLBACK_TYPES,
TYPED_GQL_STRING,
WithCustomEndpoint,
WithApiKey
>,
options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING, Options>,
additionalHeaders?: CustomHeaders | undefined,
) => GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING>;

Expand Down Expand Up @@ -530,9 +516,6 @@ export interface AuthModeParams extends Record<string, unknown> {
authToken?: string;
}

export type GenerateServerClientParams<
WithCustomEndpoint extends boolean,
WithApiKey extends boolean,
> = {
export type GenerateServerClientParams = {
config: ResourcesConfig;
} & CommonPublicClientOptions<WithCustomEndpoint, WithApiKey>;
} & CommonPublicClientOptions;
Loading

0 comments on commit 93b5136

Please sign in to comment.