diff --git a/.vscode/launch.json b/.vscode/launch.json index 116f5ef9480..7a5d2c24080 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,7 @@ "--inspect-brk", "${workspaceRoot}/node_modules/.bin/jest", // Optionally specify a single test file to run/debug: - "generateClient.test.ts", + "AWSAppSyncRealTimeProvider.test.ts", "--runInBand", "--testTimeout", "600000", // 10 min timeout so jest doesn't error while we're stepping through code diff --git a/packages/api-graphql/__tests__/AWSAppSyncRealTimeProvider.test.ts b/packages/api-graphql/__tests__/AWSAppSyncRealTimeProvider.test.ts index 4500ce8a566..0675cc0fcaa 100644 --- a/packages/api-graphql/__tests__/AWSAppSyncRealTimeProvider.test.ts +++ b/packages/api-graphql/__tests__/AWSAppSyncRealTimeProvider.test.ts @@ -1104,6 +1104,33 @@ describe('AWSAppSyncRealTimeProvider', () => { ); }); + test('authenticating with AWS_LAMBDA/custom w/ custom header function that accepts request options', async () => { + expect.assertions(2); + + provider + .subscribe({ + appSyncGraphqlEndpoint: 'ws://localhost:8080', + authenticationType: 'none', + additionalHeaders: async requestOptions => { + expect(requestOptions).toEqual( + expect.objectContaining({ + queryString: '', + url: 'ws://localhost:8080', + }) + ); + return { Authorization: 'test' }; + }, + }) + .subscribe({ error: () => {} }); + + await fakeWebSocketInterface?.readyForUse; + + expect(loggerSpy).toHaveBeenCalledWith( + 'DEBUG', + 'Authenticating with "none"' + ); + }); + test('authenticating with AWS_LAMBDA/custom without Authorization', async () => { expect.assertions(1); diff --git a/packages/api-graphql/__tests__/__snapshots__/generateClient.test.ts.snap b/packages/api-graphql/__tests__/__snapshots__/generateClient.test.ts.snap index 15e016542db..2cedf31b865 100644 --- a/packages/api-graphql/__tests__/__snapshots__/generateClient.test.ts.snap +++ b/packages/api-graphql/__tests__/__snapshots__/generateClient.test.ts.snap @@ -2772,6 +2772,63 @@ exports[`generateClient basic model operations - custom client and request heade ] `; +exports[`generateClient basic model operations - custom client and request headers can create() - with custom client header functions that pass requestOptions 1`] = ` +[ + [ + { + "abortController": AbortController {}, + "options": { + "body": { + "query": "mutation ($input: CreateTodoInput!) { + createTodo(input: $input) { + id + name + description + status + tags + createdAt + updatedAt + todoMetaId + owner + } +} +", + "variables": { + "input": { + "description": "something something", + "name": "some name", + }, + }, + }, + "headers": { + "X-Api-Key": "FAKE-KEY", + "rq-method": "POST", + "rq-qs": "mutation ($input: CreateTodoInput!) { + createTodo(input: $input) { + id + name + description + status + tags + createdAt + updatedAt + todoMetaId + owner + } +} +", + "rq-url": "https://localhost/graphql", + "x-amz-user-agent": "aws-amplify/latest api/latest framework/latest", + }, + "signingServiceInfo": undefined, + "withCredentials": undefined, + }, + "url": "https://localhost/graphql", + }, + ], +] +`; + exports[`generateClient basic model operations - custom client and request headers can create() - with custom client headers 1`] = ` [ [ @@ -2856,6 +2913,63 @@ exports[`generateClient basic model operations - custom client and request heade ] `; +exports[`generateClient basic model operations - custom client and request headers can create() - with custom request header function that accept requestOptions 1`] = ` +[ + [ + { + "abortController": AbortController {}, + "options": { + "body": { + "query": "mutation ($input: CreateTodoInput!) { + createTodo(input: $input) { + id + name + description + status + tags + createdAt + updatedAt + todoMetaId + owner + } +} +", + "variables": { + "input": { + "description": "something something", + "name": "some name", + }, + }, + }, + "headers": { + "X-Api-Key": "FAKE-KEY", + "rq-method": "POST", + "rq-qs": "mutation ($input: CreateTodoInput!) { + createTodo(input: $input) { + id + name + description + status + tags + createdAt + updatedAt + todoMetaId + owner + } +} +", + "rq-url": "https://localhost/graphql", + "x-amz-user-agent": "aws-amplify/latest api/latest framework/latest", + }, + "signingServiceInfo": undefined, + "withCredentials": undefined, + }, + "url": "https://localhost/graphql", + }, + ], +] +`; + exports[`generateClient basic model operations - custom client and request headers can create() - with custom request headers 1`] = ` [ [ diff --git a/packages/api-graphql/__tests__/generateClient.test.ts b/packages/api-graphql/__tests__/generateClient.test.ts index d445335c94b..9951586e20e 100644 --- a/packages/api-graphql/__tests__/generateClient.test.ts +++ b/packages/api-graphql/__tests__/generateClient.test.ts @@ -66,23 +66,23 @@ function makeAppSyncStreams() { * replaces fields that are likely to change between calls (or library version revs) * with static values. When possible, on the unpredicable portions of these values * are replaced. - * + * * ## THIS IS DESTRUCTIVE - * + * * The original `spy.mocks.calls` will be updated *and* returned. - * + * * For example, - * + * * ```plain * headers.x-amz-user-agent: "aws-amplify/6.0.5 api/1 framework/0" * ``` - * + * * Is replaced with: - * + * * ```plain * headers.x-amz-user-agent: "aws-amplify/latest api/latest framework/latest" * ``` - * + * * @param spy The Jest spy */ function normalizePostGraphqlCalls(spy: jest.SpyInstance) { @@ -251,7 +251,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -272,7 +272,7 @@ describe('generateClient', () => { ...serverManagedFields, name: 'some name', description: 'something something', - tags: ['one', 'two', 'three'] + tags: ['one', 'two', 'three'], }, }, }); @@ -280,7 +280,7 @@ describe('generateClient', () => { const client = generateClient({ amplify: Amplify }); const { data } = await client.models.Todo.get({ id: 'asdf' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -289,7 +289,7 @@ describe('generateClient', () => { owner: 'wirejobviously', name: 'some name', description: 'something something', - tags: ['one', 'two', 'three'] + tags: ['one', 'two', 'three'], }) ); }); @@ -315,8 +315,8 @@ describe('generateClient', () => { filter: { name: { contains: 'name' } }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() - + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); + expect(data.length).toBe(1); expect(data[0]).toEqual( expect.objectContaining({ @@ -351,7 +351,7 @@ describe('generateClient', () => { nextToken: 'some-token', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can list() with limit', async () => { @@ -376,7 +376,7 @@ describe('generateClient', () => { limit: 5, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can update()', async () => { @@ -397,7 +397,7 @@ describe('generateClient', () => { name: 'some other name', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -427,7 +427,7 @@ describe('generateClient', () => { id: 'some-id', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -590,7 +590,7 @@ describe('generateClient', () => { const { data: notes } = await data.notes(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); expect(notes!.length).toBe(1); expect(notes![0]).toEqual( @@ -636,7 +636,7 @@ describe('generateClient', () => { const { data: notes } = await data.notes({ nextToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); expect(notes!.length).toBe(1); expect(notes![0]).toEqual( @@ -682,7 +682,7 @@ describe('generateClient', () => { const { data: notes } = await data.notes({ limit: 5 }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); expect(notes!.length).toBe(1); expect(notes![0]).toEqual( @@ -725,7 +725,7 @@ describe('generateClient', () => { const { data: todo } = await data.todo(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); expect(todo).toEqual( expect.objectContaining({ @@ -766,7 +766,7 @@ describe('generateClient', () => { const { data: todo } = await data.meta(); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); expect(todo).toEqual( expect.objectContaining({ @@ -823,7 +823,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can get()', async () => { @@ -841,7 +841,7 @@ describe('generateClient', () => { const client = generateClient({ amplify: Amplify }); await client.models.Todo.get({ id: 'asdf' }, { authMode: 'userPool' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can list()', async () => { @@ -866,7 +866,7 @@ describe('generateClient', () => { authMode: 'userPool', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can update()', async () => { @@ -890,7 +890,7 @@ describe('generateClient', () => { { authMode: 'userPool' } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can delete()', async () => { @@ -913,7 +913,7 @@ describe('generateClient', () => { { authMode: 'userPool' } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can subscribe to onCreate()', done => { @@ -1064,7 +1064,7 @@ describe('generateClient', () => { await data.notes(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -1102,7 +1102,7 @@ describe('generateClient', () => { await data.todo(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -1139,7 +1139,7 @@ describe('generateClient', () => { await data.meta(); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); @@ -1180,7 +1180,7 @@ describe('generateClient', () => { await data.notes({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -1218,7 +1218,7 @@ describe('generateClient', () => { await data.todo({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -1255,7 +1255,7 @@ describe('generateClient', () => { await data.meta({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); }); @@ -1306,7 +1306,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can get()', async () => { @@ -1327,7 +1327,7 @@ describe('generateClient', () => { { authMode: 'lambda', authToken: 'some-token' } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can list()', async () => { @@ -1353,7 +1353,7 @@ describe('generateClient', () => { authToken: 'some-token', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can update()', async () => { @@ -1377,7 +1377,7 @@ describe('generateClient', () => { { authMode: 'lambda', authToken: 'some-token' } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can delete()', async () => { @@ -1400,7 +1400,7 @@ describe('generateClient', () => { { authMode: 'lambda', authToken: 'some-token' } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can subscribe to onCreate()', done => { @@ -1554,7 +1554,7 @@ describe('generateClient', () => { await data.notes(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -1593,7 +1593,7 @@ describe('generateClient', () => { await data.todo(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -1631,7 +1631,7 @@ describe('generateClient', () => { await data.meta(); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); @@ -1672,7 +1672,7 @@ describe('generateClient', () => { await data.notes({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -1710,7 +1710,7 @@ describe('generateClient', () => { await data.todo({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -1747,7 +1747,7 @@ describe('generateClient', () => { await data.meta({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); }); @@ -1795,7 +1795,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can get()', async () => { @@ -1816,7 +1816,7 @@ describe('generateClient', () => { }); await client.models.Todo.get({ id: 'asdf' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can list()', async () => { @@ -1843,7 +1843,7 @@ describe('generateClient', () => { filter: { name: { contains: 'name' } }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can update()', async () => { @@ -1867,7 +1867,7 @@ describe('generateClient', () => { name: 'some other name', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can delete()', async () => { @@ -1890,7 +1890,7 @@ describe('generateClient', () => { id: 'some-id', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can subscribe to onCreate()', done => { @@ -2044,7 +2044,7 @@ describe('generateClient', () => { await data.notes(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -2080,7 +2080,7 @@ describe('generateClient', () => { await data.todo(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -2115,7 +2115,7 @@ describe('generateClient', () => { await data.meta(); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); @@ -2156,7 +2156,7 @@ describe('generateClient', () => { await data.notes({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -2192,7 +2192,7 @@ describe('generateClient', () => { await data.todo({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -2227,7 +2227,7 @@ describe('generateClient', () => { await data.meta({ authMode: 'apiKey' }); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); }); @@ -2276,7 +2276,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can get()', async () => { @@ -2298,7 +2298,7 @@ describe('generateClient', () => { }); await client.models.Todo.get({ id: 'asdf' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can list()', async () => { @@ -2326,7 +2326,7 @@ describe('generateClient', () => { filter: { name: { contains: 'name' } }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can update()', async () => { @@ -2351,7 +2351,7 @@ describe('generateClient', () => { name: 'some other name', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can delete()', async () => { @@ -2375,7 +2375,7 @@ describe('generateClient', () => { id: 'some-id', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can subscribe to onCreate()', done => { @@ -2533,7 +2533,7 @@ describe('generateClient', () => { await data.notes(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -2570,7 +2570,7 @@ describe('generateClient', () => { await data.todo(); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -2606,7 +2606,7 @@ describe('generateClient', () => { await data.meta(); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); @@ -2647,7 +2647,7 @@ describe('generateClient', () => { await data.notes({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @belongsTo', async () => { @@ -2683,7 +2683,7 @@ describe('generateClient', () => { await data.todo({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildNotesSpy)).toMatchSnapshot(); }); test('can lazy load @hasOne', async () => { @@ -2718,7 +2718,7 @@ describe('generateClient', () => { await data.meta({ authMode: 'lambda', authToken: 'some-token' }); - expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(getChildMetaSpy)).toMatchSnapshot(); }); }); }); @@ -2758,7 +2758,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -2795,7 +2795,46 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); + + expect(data).toEqual( + expect.objectContaining({ + __typename: 'Todo', + id: 'some-id', + owner: 'wirejobviously', + name: 'some name', + description: 'something something', + }) + ); + }); + + test('can create() - with custom client header functions that pass requestOptions', async () => { + const spy = mockApiResponse({ + data: { + createTodo: { + __typename: 'Todo', + ...serverManagedFields, + name: 'some name', + description: 'something something', + }, + }, + }); + + const client = generateClient({ + amplify: Amplify, + headers: async requestOptions => ({ + 'rq-url': requestOptions?.url || 'should-not-be-present', + 'rq-qs': requestOptions?.queryString || 'should-not-be-present', + 'rq-method': requestOptions?.method || 'should-not-be-present', + }), + }); + + const { data } = await client.models.Todo.create({ + name: 'some name', + description: 'something something', + }); + + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -2839,7 +2878,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); // Request headers should overwrite client headers: expect(spy).toHaveBeenCalledWith( @@ -2894,7 +2933,53 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); + + expect(data).toEqual( + expect.objectContaining({ + __typename: 'Todo', + id: 'some-id', + owner: 'wirejobviously', + name: 'some name', + description: 'something something', + }) + ); + }); + + test('can create() - with custom request header function that accept requestOptions', async () => { + const spy = mockApiResponse({ + data: { + createTodo: { + __typename: 'Todo', + ...serverManagedFields, + name: 'some name', + description: 'something something', + }, + }, + }); + + const client = generateClient({ + amplify: Amplify, + headers: { + 'client-header': 'should not exist', + }, + }); + + const { data } = await client.models.Todo.create( + { + name: 'some name', + description: 'something something', + }, + { + headers: async requestOptions => ({ + 'rq-url': requestOptions?.url || 'should-not-be-present', + 'rq-qs': requestOptions?.queryString || 'should-not-be-present', + 'rq-method': requestOptions?.method || 'should-not-be-present', + }), + } + ); + + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -2927,7 +3012,7 @@ describe('generateClient', () => { }); const { data } = await client.models.Todo.get({ id: 'asdf' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -2967,7 +3052,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3006,7 +3091,7 @@ describe('generateClient', () => { filter: { name: { contains: 'name' } }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data.length).toBe(1); expect(data[0]).toEqual( @@ -3049,7 +3134,7 @@ describe('generateClient', () => { }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -3097,7 +3182,7 @@ describe('generateClient', () => { name: 'some other name', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3140,7 +3225,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3175,7 +3260,7 @@ describe('generateClient', () => { id: 'some-id', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('can delete() - with custom request headers', async () => { @@ -3207,7 +3292,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3313,6 +3398,50 @@ describe('generateClient', () => { }); }); + test('can subscribe to onCreate() - with a custom header function that accepts requestOptions', done => { + const noteToSend = { + __typename: 'Note', + ...serverManagedFields, + body: 'a very good note', + }; + + const graphqlMessage = { + data: { + onCreateNote: noteToSend, + }, + }; + + const graphqlVariables = { + filter: { + body: { contains: 'good note' }, + }, + }; + + const client = generateClient({ amplify: Amplify }); + + const spy = jest.fn(() => from([graphqlMessage])); + (raw.GraphQLAPI as any).appSyncRealTime = { subscribe: spy }; + + client.models.Note.onCreate({ + filter: graphqlVariables.filter, + headers: async requestOptions => ({ + 'rq-url': requestOptions?.url || 'should-not-be-present', + 'rq-qs': requestOptions?.queryString || 'should-not-be-present', + 'rq-method': requestOptions?.method || 'should-not-be-present', + }), + }).subscribe({ + next(value) { + expectSubWithHeadersFn(spy, 'onCreateNote', graphqlVariables); + expect(value).toEqual(expect.objectContaining(noteToSend)); + done(); + }, + error(error) { + expect(error).toBeUndefined(); + done('bad news!'); + }, + }); + }); + test('can subscribe to onUpdate()', done => { const noteToSend = { __typename: 'Note', @@ -3451,7 +3580,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3488,7 +3617,7 @@ describe('generateClient', () => { description: 'something something', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3529,7 +3658,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3562,7 +3691,7 @@ describe('generateClient', () => { }); const { data } = await client.models.Todo.get({ id: 'asdf' }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3602,7 +3731,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3641,7 +3770,7 @@ describe('generateClient', () => { filter: { name: { contains: 'name' } }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data.length).toBe(1); expect(data[0]).toEqual( @@ -3684,7 +3813,7 @@ describe('generateClient', () => { }, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(spy).toHaveBeenCalledWith( expect.objectContaining({ @@ -3732,7 +3861,7 @@ describe('generateClient', () => { name: 'some other name', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3775,7 +3904,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3810,7 +3939,7 @@ describe('generateClient', () => { id: 'some-id', }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -3852,7 +3981,7 @@ describe('generateClient', () => { } ); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); expect(data).toEqual( expect.objectContaining({ @@ -4126,7 +4255,7 @@ describe('generateClient', () => { }), ]); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); done(); } @@ -4806,7 +4935,7 @@ describe('generateClient', () => { query: `query { listTodos { __typename id owner createdAt updatedAt name description } }`, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); }); @@ -4849,7 +4978,7 @@ describe('generateClient', () => { query: `query { listTodos { __typename id owner createdAt updatedAt name description } }`, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); test('client auth override query - lambda', async () => { @@ -4878,7 +5007,7 @@ describe('generateClient', () => { query: `query { listTodos { __typename id owner createdAt updatedAt name description } }`, }); - expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot() + expect(normalizePostGraphqlCalls(spy)).toMatchSnapshot(); }); }); }); diff --git a/packages/api-graphql/package.json b/packages/api-graphql/package.json index bc0884f65c3..8febfc6b226 100644 --- a/packages/api-graphql/package.json +++ b/packages/api-graphql/package.json @@ -72,7 +72,7 @@ }, "homepage": "https://aws-amplify.github.io/", "devDependencies": { - "@aws-amplify/data-schema": "^0.12.9", + "@aws-amplify/data-schema": "^0.12.11", "@rollup/plugin-typescript": "11.1.5", "rollup": "3.29.4", "typescript": "5.0.2" @@ -87,7 +87,7 @@ "dependencies": { "@aws-amplify/api-rest": "4.0.7", "@aws-amplify/core": "6.0.7", - "@aws-amplify/data-schema-types": "^0.6.6", + "@aws-amplify/data-schema-types": "^0.6.10", "@aws-sdk/types": "3.387.0", "graphql": "15.8.0", "rxjs": "^7.8.1", diff --git a/packages/api-graphql/src/Providers/AWSAppSyncRealTimeProvider/index.ts b/packages/api-graphql/src/Providers/AWSAppSyncRealTimeProvider/index.ts index a8fb82a05ce..f4d5fdb8a4f 100644 --- a/packages/api-graphql/src/Providers/AWSAppSyncRealTimeProvider/index.ts +++ b/packages/api-graphql/src/Providers/AWSAppSyncRealTimeProvider/index.ts @@ -50,6 +50,7 @@ import { ReconnectEvent, ReconnectionMonitor, } from '../../utils/ReconnectionMonitor'; +import { CustomHeaders, RequestOptions } from '@aws-amplify/data-schema-types'; const logger = new ConsoleLogger('AWSAppSyncRealTimeProvider'); @@ -98,9 +99,7 @@ export interface AWSAppSyncRealTimeProviderOptions { apiKey?: string; region?: string; libraryConfigHeaders?: () => {} | (() => Promise<{}>); - additionalHeaders?: - | Record - | (() => Promise>); + additionalHeaders?: CustomHeaders; additionalCustomHeaders?: Record; authToken?: string; } @@ -323,7 +322,11 @@ export class AWSAppSyncRealTimeProvider { let additionalCustomHeaders: Record = {}; if (typeof additionalHeaders === 'function') { - additionalCustomHeaders = await additionalHeaders(); + const requestOptions: RequestOptions = { + url: appSyncGraphqlEndpoint || '', + queryString: query || '', + }; + additionalCustomHeaders = await additionalHeaders(requestOptions); } else { additionalCustomHeaders = additionalHeaders; } diff --git a/packages/api-graphql/src/internals/InternalGraphQLAPI.ts b/packages/api-graphql/src/internals/InternalGraphQLAPI.ts index c306fb63e09..41dab97903c 100644 --- a/packages/api-graphql/src/internals/InternalGraphQLAPI.ts +++ b/packages/api-graphql/src/internals/InternalGraphQLAPI.ts @@ -29,7 +29,7 @@ import { updateRequestToBeCancellable, } from '@aws-amplify/api-rest/internals'; import { AWSAppSyncRealTimeProvider } from '../Providers/AWSAppSyncRealTimeProvider'; -import { CustomHeaders } from '@aws-amplify/data-schema-types'; +import { CustomHeaders, RequestOptions } from '@aws-amplify/data-schema-types'; import { resolveConfig, resolveLibraryOptions } from '../utils'; import { repackageUnauthError } from '../utils/errors/repackageAuthError'; @@ -260,7 +260,15 @@ export class InternalGraphQLAPIClass { let additionalCustomHeaders: Record; if (typeof additionalHeaders === 'function') { - additionalCustomHeaders = await additionalHeaders(); + const requestOptions: RequestOptions = { + method: 'POST', + url: new AmplifyUrl( + customEndpoint || appSyncGraphqlEndpoint || '' + ).toString(), + queryString: print(query as DocumentNode), + }; + + additionalCustomHeaders = await additionalHeaders(requestOptions); } else { additionalCustomHeaders = additionalHeaders; } @@ -351,6 +359,7 @@ export class InternalGraphQLAPIClass { } let response: any; + try { const { body: responseBody } = await this._api.post({ url: new AmplifyUrl(endpoint), diff --git a/yarn.lock b/yarn.lock index bc07301cf3d..ee390b9f359 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,17 +10,17 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@aws-amplify/data-schema-types@*", "@aws-amplify/data-schema-types@^0.6.6": - version "0.6.7" - resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema-types/-/data-schema-types-0.6.7.tgz#4bf14682fe0d7174e7ef9f2c9bb3b84310b171e0" - integrity sha512-JmY1R/tuhjj/rQWGUrDR6o67K+7XFHucMVO0F4XIS2jJgOb44/J6sV9Yq9NYPVU0eMFB1Iv5YcZQlS2lGRNdqA== +"@aws-amplify/data-schema-types@*", "@aws-amplify/data-schema-types@^0.6.10": + version "0.6.10" + resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema-types/-/data-schema-types-0.6.10.tgz#e208e57dd2e7de0b9d479d19c1d8459b578df506" + integrity sha512-o893k1tNJ0iR9w9Q/jymhSQZmgNdH/L5tz+RXyWcQO+qgN3XhGaayqjYKcQ22XkB1pBgGkXtRLO6Jg74KriBWg== dependencies: rxjs "^7.8.1" -"@aws-amplify/data-schema@^0.12.9": - version "0.12.9" - resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema/-/data-schema-0.12.9.tgz#89c01c93ab0f0442529dbf20c927cbc969004d28" - integrity sha512-S0uN3ZncODzMpDijWfT5uHoytY65KTob/m9N6ltsGsk7h+1+alNkA/PAEya9JWhzIU8gFemW9F/8s9X9S/Nweg== +"@aws-amplify/data-schema@^0.12.11": + version "0.12.11" + resolved "https://registry.yarnpkg.com/@aws-amplify/data-schema/-/data-schema-0.12.11.tgz#bc43ada620a2b7311c2523891f96a0bc66ca50c3" + integrity sha512-wc7bHMrmw1+gFcY36BaZsPd08vJisfCZjjYzuXREitMHmy97HYbvva22nPbDUciQWTk+87InYflYoS5NJnKspg== dependencies: "@aws-amplify/data-schema-types" "*"