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

feat(api): Graphql custom/multi- client #14064

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
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
16 changes: 8 additions & 8 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Suppress console messages printing during unit tests.
// Comment out log level as necessary (e.g. while debugging tests)
global.console = {
...console,
log: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
};
// global.console = {
// ...console,
// log: jest.fn(),
// debug: jest.fn(),
// info: jest.fn(),
// warn: jest.fn(),
// error: jest.fn(),
// };

// React Native global
global['__DEV__'] = true;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,6 @@
},
"overrides": {
"tar": "6.2.1"
}
},
"packageManager": "[email protected]+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447"
}
104 changes: 73 additions & 31 deletions packages/adapter-nextjs/src/api/generateServerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,34 @@ import {
getAmplifyServerContext,
} from '@aws-amplify/core/internals/adapter-core';
import {
CommonPublicClientOptions,
V6ClientSSRCookies,
V6ClientSSRRequest,
} from '@aws-amplify/api-graphql';
import {
GraphQLAuthMode,
parseAmplifyConfig,
} from '@aws-amplify/core/internals/utils';
import { parseAmplifyConfig } from '@aws-amplify/core/internals/utils';

import { NextServer } from '../types';

import { createServerRunnerForAPI } from './createServerRunnerForAPI';

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

interface ReqClientParams {
type ReqClientParams<
WithEndpoint extends boolean,
WithApiKey extends boolean,
> = {
config: NextServer.CreateServerRunnerInput['config'];
authMode?: GraphQLAuthMode;
authToken?: string;
}
} & 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 @@ -44,13 +48,30 @@ interface ReqClientParams {
*/
export function generateServerClientUsingCookies<
T extends Record<any, any> = never,
>({
config,
cookies,
authMode,
authToken,
}: CookiesClientParams): V6ClientSSRCookies<T> {
if (typeof cookies !== 'function') {
>(
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> {
if (typeof options.cookies !== 'function') {
throw new AmplifyServerContextError({
message:
'generateServerClientUsingCookies is only compatible with the `cookies` Dynamic Function available in Server Components.',
Expand All @@ -61,24 +82,28 @@ export function generateServerClientUsingCookies<
}

const { runWithAmplifyServerContext, resourcesConfig } =
createServerRunnerForAPI({ config });
createServerRunnerForAPI({ config: options.config });

// This function reference gets passed down to InternalGraphQLAPI.ts.graphql
// where this._graphql is passed in as the `fn` argument
// causing it to always get invoked inside `runWithAmplifyServerContext`
const getAmplify = (fn: (amplify: any) => Promise<any>) =>
runWithAmplifyServerContext({
nextServerContext: { cookies },
nextServerContext: { cookies: options.cookies },
operation: contextSpec =>
fn(getAmplifyServerContext(contextSpec).amplify),
});

return generateClientWithAmplifyInstance<T, V6ClientSSRCookies<T>>({
const { cookies: _cookies, config: _config, ...params } = options;

return generateClientWithAmplifyInstance<
T,
V6ClientSSRCookies<T, WithCustomEndpoint, WithApiKey>
>({
amplify: getAmplify,
config: resourcesConfig,
authMode,
authToken,
});
...params,
} as any); // TS can't narrow the type here.
}

/**
Expand All @@ -99,12 +124,29 @@ export function generateServerClientUsingCookies<
*/
export function generateServerClientUsingReqRes<
T extends Record<any, any> = never,
>({ config, authMode, authToken }: ReqClientParams): V6ClientSSRRequest<T> {
const amplifyConfig = parseAmplifyConfig(config);
>(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> {
const amplifyConfig = parseAmplifyConfig(options.config);

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

return generateClient<T>({
return generateClient<T, WithCustomEndpoint, WithApiKey>({
config: amplifyConfig,
authMode,
authToken,
});
...params,
} as any); // TS can't narrow the type here.
}
1 change: 1 addition & 0 deletions packages/api-graphql/__tests__/GraphQLAPI.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,7 @@ describe('API test', () => {
const subscribeOptions = spyon_appsync_realtime.mock.calls[0][0];
expect(subscribeOptions).toBe(resolvedUrl);
});

test('graphql method handles INTERNAL_USER_AGENT_OVERRIDE correctly', async () => {
Amplify.configure({
API: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ describe('server generateClient', () => {
test('subscriptions are disabled', () => {
const getAmplify = async (fn: any) => await fn(Amplify);

const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRCookies<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: getAmplify,
config: config,
});
Expand Down Expand Up @@ -71,10 +68,7 @@ describe('server generateClient', () => {

const getAmplify = async (fn: any) => await fn(Amplify);

const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRCookies<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: getAmplify,
config: config,
});
Expand Down Expand Up @@ -118,10 +112,7 @@ describe('server generateClient', () => {

const getAmplify = async (fn: any) => await fn(Amplify);

const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRCookies<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: getAmplify,
config: config,
});
Expand Down Expand Up @@ -167,10 +158,7 @@ describe('server generateClient', () => {

const getAmplify = async (fn: any) => await fn(Amplify);

const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRCookies<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: getAmplify,
config: config,
});
Expand All @@ -197,10 +185,7 @@ describe('server generateClient', () => {

describe('with request', () => {
test('subscriptions are disabled', () => {
const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRRequest<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: null,
config: config,
});
Expand All @@ -215,10 +200,7 @@ describe('server generateClient', () => {
Amplify.configure(configFixture as any);
const config = Amplify.getConfig();

const client = generateClientWithAmplifyInstance<
Schema,
V6ClientSSRRequest<Schema>
>({
const client = generateClientWithAmplifyInstance<Schema>({
amplify: null,
config: config,
});
Expand Down
Loading