Skip to content

Commit c79048f

Browse files
committed
Updated index.mjs file to be modified for Apollo subgraph Federation 2 features
1 parent 6408f4e commit c79048f

File tree

7 files changed

+102
-7
lines changed

7 files changed

+102
-7
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,6 @@ permissions and limitations under the License.
116116
option ([#117](https://github.com/aws/amazon-neptune-for-graphql/pull/117))
117117
* Fixed invalid schema generation when AWS AppSync scalar types are used in
118118
an input
119-
schema ([#118](https://github.com/aws/amazon-neptune-for-graphql/pull/118))
119+
schema ([#118](https://github.com/aws/amazon-neptune-for-graphql/pull/118))
120+
* Updated index.mjs file to be modified for Apollo subgraph Federation 2
121+
features ([#126](https://github.com/aws/amazon-neptune-for-graphql/pull/126))

src/zipPackage.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ async function createZip({targetZipFilePath, includePaths = [], includeContent =
4949
output.on('close', () => resolve());
5050
archive.on('error', err => reject(err));
5151
});
52-
52+
5353
archive.pipe(output);
5454

5555
includePaths.forEach(includePath => {
@@ -144,4 +144,4 @@ export async function createApolloDeploymentPackage({zipFilePath, resolverFilePa
144144

145145
export function getModulePath() {
146146
return path.dirname(fileURLToPath(import.meta.url));
147-
}
147+
}

templates/ApolloServer/index.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import dotenv from 'dotenv';
88

99
dotenv.config();
1010

11-
const typeDefs = parse(readFileSync('./output.schema.graphql', 'utf-8'));
11+
const fileContent = readFileSync('./output.schema.graphql', 'utf-8');
12+
let schema = fileContent;
13+
if (process.env.SUBGRAPH === 'true') {
14+
schema = `extend schema @link(
15+
url: "https://specs.apollo.dev/federation/v2.0"
16+
import: ["@key", "@shareable"]
17+
)${fileContent}`;
18+
}
19+
const typeDefs = parse(schema);
1220
const queryDefinition = typeDefs.definitions.find(
1321
definition => definition.kind === 'ObjectTypeDefinition' && definition.name.value === 'Query'
1422
);

test/TestCases/Case09/Case09.02.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const testCase = readJSONFile('./test/TestCases/Case09/apollo-subgraph.json');
66
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
77

88
const outputFolderPath = './test/TestCases/Case09/apollo-subgraph-output';
9+
const outputReferencePath = './test/TestCases/Case09/outputReference';
910
describe('Validate Apollo Server Subgraph output artifacts', () => {
1011
afterAll(() => {
1112
fs.rmSync(outputFolderPath, {recursive: true});
@@ -19,5 +20,5 @@ describe('Validate Apollo Server Subgraph output artifacts', () => {
1920
`${testDbInfo.graphName}.source.schema.graphql`
2021
]);
2122

22-
testApolloArtifacts(outputFolderPath, testDbInfo, true);
23+
testApolloArtifacts(outputFolderPath, outputReferencePath, testDbInfo, true);
2324
});

test/TestCases/Case09/Case09.04.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import {parseNeptuneEndpoint} from "../../../src/util.js";
55
const testCase = readJSONFile('./test/TestCases/Case09/apollo-subgraph-input-schema.json');
66
const testDbInfo = parseNeptuneEndpoint(testCase.host + ':' + testCase.port);
77
const outputFolderPath = './test/TestCases/Case09/apollo-subgraph-input-schema-output';
8+
const outputReferencePath = './test/TestCases/Case09/outputReference';
89

910
describe('Validate Apollo Server Subgraph output artifacts are created when using an input schema file', () => {
1011
afterAll(async () => {
1112
fs.rmSync(outputFolderPath, {recursive: true});
1213
});
1314

14-
testApolloArtifacts(outputFolderPath, testDbInfo, true);
15+
testApolloArtifacts(outputFolderPath, outputReferencePath, testDbInfo, true);
1516
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import {ApolloServer} from '@apollo/server';
2+
import {startStandaloneServer} from '@apollo/server/standalone';
3+
import {buildSubgraphSchema} from '@apollo/subgraph';
4+
import {readFileSync} from 'fs';
5+
import {parse} from 'graphql';
6+
import {resolveEvent} from './neptune.mjs'
7+
import dotenv from 'dotenv';
8+
9+
dotenv.config();
10+
11+
const source = readFileSync('./output.schema.graphql', 'utf-8');
12+
const schema = `extend schema @link(
13+
url: "https://specs.apollo.dev/federation/v2.0"
14+
import: ["@key", "@shareable"]
15+
)${source}`;
16+
const typeDefs = parse(schema);
17+
const queryDefinition = typeDefs.definitions.find(
18+
definition => definition.kind === 'ObjectTypeDefinition' && definition.name.value === 'Query'
19+
);
20+
const queryNames = queryDefinition ? queryDefinition.fields.map(field => field.name.value) : [];
21+
22+
const mutationDefinition = typeDefs.definitions.find(
23+
definition => definition.kind === 'ObjectTypeDefinition' && definition.name.value === 'Mutation'
24+
);
25+
const mutationNames = mutationDefinition ? mutationDefinition.fields.map(field => field.name.value) : [];
26+
27+
/**
28+
* Resolves GraphQL queries and mutations by processing the info object and arguments.
29+
*
30+
* @param {Object} info - GraphQLResolveInfo object
31+
* @param {Object} args - graphQL query arguments
32+
* @returns {Promise<*>} Resolved data from the event processor
33+
*/
34+
function resolve(info, args) {
35+
if (!info?.fieldName) {
36+
throw new Error('Missing fieldName on GraphQLResolveInfo');
37+
}
38+
if (!Array.isArray(info.fieldNodes) || info.fieldNodes.length !== 1) {
39+
throw new Error('Invalid fieldNodes on GraphQLResolveInfo');
40+
}
41+
const event = {
42+
field: info.fieldName,
43+
arguments: args,
44+
selectionSet: info.fieldNodes[0].selectionSet,
45+
variables: info.variableValues,
46+
fragments: info.fragments
47+
};
48+
49+
return resolveEvent(event).then((result) => {
50+
return result;
51+
});
52+
}
53+
54+
const resolvers = {
55+
Query: queryNames.reduce((accumulator, queryName) => {
56+
accumulator[queryName] = (parent, args, context, info) => {
57+
return resolve(info, args);
58+
};
59+
return accumulator;
60+
}, {}),
61+
62+
Mutation: mutationNames.reduce((accumulator, mutationName) => {
63+
accumulator[mutationName] = (parent, args, context, info) => {
64+
return resolve(info, args);
65+
};
66+
return accumulator;
67+
}, {}),
68+
};
69+
70+
const server = process.env.SUBGRAPH === 'true' ? new ApolloServer({
71+
schema: buildSubgraphSchema([{
72+
typeDefs,
73+
resolvers
74+
}])
75+
}) : new ApolloServer({typeDefs, resolvers});
76+
77+
const {url} = await startStandaloneServer(server);
78+
console.log(`🚀 Server ready at ${url}`);

test/testLib.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ async function testResolverQueriesResults(resolverFile, queriesReferenceFolder,
185185
* Validates that an apollo zip contains the correct content.
186186
*
187187
* @param {string} outputFolderPath the test output folder path that contains the apollo zip file to validate
188+
* @param outputReferencePath the test output reference folder path that contains apollo files for content validation
188189
* @param {object} testDbInfo object that contains info about the neptune db/graph used to generate the apollo zip file
189190
* @param {string} testDbInfo.graphName neptune db/graph name
190191
* @param {string} testDbInfo.neptuneType neptune-db or neptune-graph
@@ -194,7 +195,7 @@ async function testResolverQueriesResults(resolverFile, queriesReferenceFolder,
194195
* @param {boolean} subgraph true if the apollo zip contents should be for a subgraph
195196
* @returns {Promise<void>}
196197
*/
197-
async function testApolloArtifacts(outputFolderPath, testDbInfo, subgraph = false) {
198+
async function testApolloArtifacts(outputFolderPath, outputReferencePath, testDbInfo, subgraph = false) {
198199
test('Validate Apollo zip contents', () => {
199200
const expectedFiles = [
200201
'.env',
@@ -226,6 +227,10 @@ async function testApolloArtifacts(outputFolderPath, testDbInfo, subgraph = fals
226227
];
227228
const actualEnvContent = fs.readFileSync(path.join(outputFolderPath, 'unzipped', '.env'), 'utf8');
228229
expect(actualEnvContent).toEqual(expectedEnvContent.join('\n'));
230+
231+
const expectedIndexFileContent = fs.readFileSync(path.join(outputReferencePath, 'index.mjs'), 'utf8');
232+
const actualIndexFileContent = fs.readFileSync(path.join(outputFolderPath, 'unzipped', 'index.mjs'), 'utf8');
233+
expect(actualIndexFileContent).toEqual(expectedIndexFileContent);
229234
});
230235
}
231236

0 commit comments

Comments
 (0)