Skip to content

Add assertions and type safety after #61 #69

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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: 11 additions & 5 deletions templates/JSResolverOCHTTPSTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/

import { astFromValue, buildASTSchema, typeFromAST } from 'graphql';
import assert from 'node:assert';
import { astFromValue, buildASTSchema, isInputType, typeFromAST } from 'graphql';
import { gql } from 'graphql-tag'; // GraphQL library to parse the GraphQL query

const useCallSubquery = false;
Expand All @@ -27,12 +28,17 @@ const schema = buildASTSchema(schemaDataModel, { assumeValidSDL: true });
export function resolveGraphDBQueryFromAppSyncEvent(event) {
const fieldDef = getFieldDef(event.field);

assert(fieldDef);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For troubleshooting would be nice to add a value for the optional message parameter to indicate what expected state was not satisfied ie. Field definition for ${event.field} not found.


const args = [];
for (const inputDef of fieldDef.arguments) {
for (const inputDef of fieldDef.arguments ?? []) {
const value = event.arguments[inputDef.name.value];

if (value) {
const inputType = typeFromAST(schema, inputDef.type);

assert(isInputType(inputType));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For troubleshooting would be nice to add a value for the optional message parameter to indicate what expected state was not satisfied ie. Type ${inputType} is not a valid input type.


args.push({
kind: 'Argument',
name: { kind: 'Name', value: inputDef.name.value },
Expand Down Expand Up @@ -99,8 +105,8 @@ function getTypeDefs(typeNameOrNames) {
function getFieldDef(fieldName) {
const rootTypeDefs = getRootTypeDefs();

for (const rootDef of rootTypeDefs) {
const fieldDef = rootDef.fields.find(def => def.name.value === fieldName);
for (const rootTypeDef of rootTypeDefs) {
const fieldDef = rootTypeDef.fields?.find(def => def.name.value === fieldName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the Case03 which is not currently asserting any validation after the utility is executed can be repurposed to verify error handling for scenarios addressed in this PR (app sync event fields do not match up with the graphQL schema). This could be done by using similar approach to your Case01.05.test.js tests except modifying the app sync event to reference unknown types.


if (fieldDef) {
return fieldDef;
Expand Down Expand Up @@ -1080,7 +1086,7 @@ function parseQueryInput(queryObjOrStr) {
* Accepts a GraphQL document or query string and outputs the graphDB query.
*
* @param {(Object|string)} queryObjOrStr the GraphQL document containing an operation to resolve
* @returns {string}
* @returns {Object}
*/
export function resolveGraphDBQuery(queryObjOrStr) {
let executeQuery = { query:'', parameters: {}, language: 'opencypher', refactorOutput: null };
Expand Down
18 changes: 12 additions & 6 deletions test/TestCases/Case01/outputReference/output.jsresolver.graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/

import { astFromValue, buildASTSchema, typeFromAST } from 'graphql';
import assert from 'node:assert';
import { astFromValue, buildASTSchema, isInputType, typeFromAST } from 'graphql';
import { gql } from 'graphql-tag'; // GraphQL library to parse the GraphQL query

const useCallSubquery = false;

// 2025-02-05T01:35:32.969Z
// 2025-02-09T22:45:48.901Z

const schemaDataModelJSON = `{
"kind": "Document",
Expand Down Expand Up @@ -3478,12 +3479,17 @@ const schema = buildASTSchema(schemaDataModel, { assumeValidSDL: true });
export function resolveGraphDBQueryFromAppSyncEvent(event) {
const fieldDef = getFieldDef(event.field);

assert(fieldDef);

const args = [];
for (const inputDef of fieldDef.arguments) {
for (const inputDef of fieldDef.arguments ?? []) {
const value = event.arguments[inputDef.name.value];

if (value) {
const inputType = typeFromAST(schema, inputDef.type);

assert(isInputType(inputType));

args.push({
kind: 'Argument',
name: { kind: 'Name', value: inputDef.name.value },
Expand Down Expand Up @@ -3550,8 +3556,8 @@ function getTypeDefs(typeNameOrNames) {
function getFieldDef(fieldName) {
const rootTypeDefs = getRootTypeDefs();

for (const rootDef of rootTypeDefs) {
const fieldDef = rootDef.fields.find(def => def.name.value === fieldName);
for (const rootTypeDef of rootTypeDefs) {
const fieldDef = rootTypeDef.fields?.find(def => def.name.value === fieldName);

if (fieldDef) {
return fieldDef;
Expand Down Expand Up @@ -4531,7 +4537,7 @@ function parseQueryInput(queryObjOrStr) {
* Accepts a GraphQL document or query string and outputs the graphDB query.
*
* @param {(Object|string)} queryObjOrStr the GraphQL document containing an operation to resolve
* @returns {string}
* @returns {Object}
*/
export function resolveGraphDBQuery(queryObjOrStr) {
let executeQuery = { query:'', parameters: {}, language: 'opencypher', refactorOutput: null };
Expand Down
18 changes: 12 additions & 6 deletions test/TestCases/Case01/outputReference/output.resolver.graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/

import { astFromValue, buildASTSchema, typeFromAST } from 'graphql';
import assert from 'node:assert';
import { astFromValue, buildASTSchema, isInputType, typeFromAST } from 'graphql';
import { gql } from 'graphql-tag'; // GraphQL library to parse the GraphQL query

const useCallSubquery = false;

// 2025-02-05T01:35:32.969Z
// 2025-02-09T22:45:48.901Z

const schemaDataModelJSON = `{
"kind": "Document",
Expand Down Expand Up @@ -3478,12 +3479,17 @@ const schema = buildASTSchema(schemaDataModel, { assumeValidSDL: true });
export function resolveGraphDBQueryFromAppSyncEvent(event) {
const fieldDef = getFieldDef(event.field);

assert(fieldDef);

const args = [];
for (const inputDef of fieldDef.arguments) {
for (const inputDef of fieldDef.arguments ?? []) {
const value = event.arguments[inputDef.name.value];

if (value) {
const inputType = typeFromAST(schema, inputDef.type);

assert(isInputType(inputType));

args.push({
kind: 'Argument',
name: { kind: 'Name', value: inputDef.name.value },
Expand Down Expand Up @@ -3550,8 +3556,8 @@ function getTypeDefs(typeNameOrNames) {
function getFieldDef(fieldName) {
const rootTypeDefs = getRootTypeDefs();

for (const rootDef of rootTypeDefs) {
const fieldDef = rootDef.fields.find(def => def.name.value === fieldName);
for (const rootTypeDef of rootTypeDefs) {
const fieldDef = rootTypeDef.fields?.find(def => def.name.value === fieldName);

if (fieldDef) {
return fieldDef;
Expand Down Expand Up @@ -4531,7 +4537,7 @@ function parseQueryInput(queryObjOrStr) {
* Accepts a GraphQL document or query string and outputs the graphDB query.
*
* @param {(Object|string)} queryObjOrStr the GraphQL document containing an operation to resolve
* @returns {string}
* @returns {Object}
*/
export function resolveGraphDBQuery(queryObjOrStr) {
let executeQuery = { query:'', parameters: {}, language: 'opencypher', refactorOutput: null };
Expand Down
5 changes: 1 addition & 4 deletions test/TestCases/Case02/case.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
"description":"Start from graph db json, from Air Routes db",
"argv":[ "--quiet",
"--input-graphdb-schema-file", "./test/TestCases/Case02/input/airports.graphdb.json",
"--output-js-resolver-file", "./test/TestCases/Case02/output/output.jsresolver.graphql.js",
"--output-folder-path", "./test/TestCases/Case02/output",
"--output-no-lambda-zip"],
"host": "<AIR_ROUTES_DB_HOST>",
"port": "<AIR_ROUTES_DB_PORT>",
"testOutputFilesSize": ["output.lambda.zip", "output.resolver.graphql.js", "output.schema.graphql", "output.source.schema.graphql"],
"testOutputFilesContent": ["output.schema.graphql", "output.source.schema.graphql"]
"port": "<AIR_ROUTES_DB_PORT>"
}
4 changes: 1 addition & 3 deletions test/TestCases/Case05/case01.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,5 @@
"--create-update-aws-pipeline-neptune-endpoint", "<AIR_ROUTES_DB_HOST>:<AIR_ROUTES_DB_PORT>",
"--output-resolver-query-https"],
"host": "<AIR_ROUTES_DB_HOST>",
"port": "<AIR_ROUTES_DB_PORT>",
"testOutputFilesSize": ["output.resolver.graphql.js", "output.schema.graphql", "output.source.schema.graphql"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're cleaning up test files with unused fields can you also do the same for Case03/case.json?

"testOutputFilesContent": ["output.schema.graphql", "output.source.schema.graphql"]
"port": "<AIR_ROUTES_DB_PORT>"
}
4 changes: 1 addition & 3 deletions test/TestCases/Case05/case02.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@
"--remove-aws-pipeline-name", "AirportsJestTest",
"--output-folder-path", "./test/TestCases/Case05/output"],
"host": "<AIR_ROUTES_DB_HOST>",
"port": "<AIR_ROUTES_DB_HOST>",
"testOutputFilesSize": ["output.resolver.graphql.js", "output.schema.graphql", "output.source.schema.graphql"],
"testOutputFilesContent": ["output.schema.graphql", "output.source.schema.graphql"]
"port": "<AIR_ROUTES_DB_HOST>"
}
4 changes: 1 addition & 3 deletions test/TestCases/Case06/case.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,5 @@
"--output-aws-pipeline-cdk-neptune-endpoint", "<AIR_ROUTES_DB_HOST>:<AIR_ROUTES_DB_PORT>",
"--output-resolver-query-https"],
"host": "<AIR_ROUTES_DB_HOST>",
"port": "<AIR_ROUTES_DB_PORT>",
"testOutputFilesSize": ["output.resolver.graphql.js", "output.schema.graphql", "output.source.schema.graphql"],
"testOutputFilesContent": ["output.schema.graphql", "output.source.schema.graphql"]
"port": "<AIR_ROUTES_DB_PORT>"
}
18 changes: 12 additions & 6 deletions test/TestCases/Case07/outputReference/output.resolver.graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ express or implied. See the License for the specific language governing
permissions and limitations under the License.
*/

import { astFromValue, buildASTSchema, typeFromAST } from 'graphql';
import assert from 'node:assert';
import { astFromValue, buildASTSchema, isInputType, typeFromAST } from 'graphql';
import { gql } from 'graphql-tag'; // GraphQL library to parse the GraphQL query

const useCallSubquery = false;

// 2025-02-05T01:37:03.182Z
// 2025-02-10T01:07:02.065Z

const schemaDataModelJSON = `{
"kind": "Document",
Expand Down Expand Up @@ -3510,12 +3511,17 @@ const schema = buildASTSchema(schemaDataModel, { assumeValidSDL: true });
export function resolveGraphDBQueryFromAppSyncEvent(event) {
const fieldDef = getFieldDef(event.field);

assert(fieldDef);

const args = [];
for (const inputDef of fieldDef.arguments) {
for (const inputDef of fieldDef.arguments ?? []) {
const value = event.arguments[inputDef.name.value];

if (value) {
const inputType = typeFromAST(schema, inputDef.type);

assert(isInputType(inputType));

args.push({
kind: 'Argument',
name: { kind: 'Name', value: inputDef.name.value },
Expand Down Expand Up @@ -3582,8 +3588,8 @@ function getTypeDefs(typeNameOrNames) {
function getFieldDef(fieldName) {
const rootTypeDefs = getRootTypeDefs();

for (const rootDef of rootTypeDefs) {
const fieldDef = rootDef.fields.find(def => def.name.value === fieldName);
for (const rootTypeDef of rootTypeDefs) {
const fieldDef = rootTypeDef.fields?.find(def => def.name.value === fieldName);

if (fieldDef) {
return fieldDef;
Expand Down Expand Up @@ -4563,7 +4569,7 @@ function parseQueryInput(queryObjOrStr) {
* Accepts a GraphQL document or query string and outputs the graphDB query.
*
* @param {(Object|string)} queryObjOrStr the GraphQL document containing an operation to resolve
* @returns {string}
* @returns {Object}
*/
export function resolveGraphDBQuery(queryObjOrStr) {
let executeQuery = { query:'', parameters: {}, language: 'opencypher', refactorOutput: null };
Expand Down