Skip to content

Commit

Permalink
fix(load): handle parse errors correctly when it gets a string
Browse files Browse the repository at this point in the history
  • Loading branch information
ardatan committed Nov 27, 2024
1 parent a9dbd3b commit 1e02935
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-hairs-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-tools/utils': patch
---

Handle parse errors correctly when loader gets a string directly
21 changes: 21 additions & 0 deletions packages/load/tests/loaders/schema/schema-from-string.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '../../../../testing/to-be-similar-string';
import '../../../../testing/to-be-similar-gql-doc';
import { printSchema } from 'graphql';
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { loadSchema, loadSchemaSync } from '@graphql-tools/load';
import { printSchemaWithDirectives } from '@graphql-tools/utils';
import { runTests, useMonorepo } from '../../../../testing/utils.js';
Expand Down Expand Up @@ -76,5 +77,25 @@ describe('schema from string', () => {
}
`);
});
it('should throw parse error', async () => {
const schemaString = `
extend type Query {
test(id: String!): Test
@resolveTo(
sourceName: "Test"
sourceTypeName: "Test"
sourceFieldName: "test"
requiredSelectionSet: "{ ...on Test { id name } }",
sourceArgs: { testId: {root.id} }
returnType: Test
)
}
`;
await expect(
load(schemaString, {
loaders: [new GraphQLFileLoader()],
}),
).rejects.toThrowError('Syntax Error');
});
});
});
21 changes: 19 additions & 2 deletions packages/utils/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { ASTNode, parse } from 'graphql';

function isURL(str: string): boolean {
try {
const url = new URL(str);
return !!url;
} catch (e) {
return false;
}
}

export const asArray = <T>(fns: T | T[]) => (Array.isArray(fns) ? fns : fns ? [fns] : []);

const invalidDocRegex = /\.[a-z0-9]+$/i;
Expand All @@ -13,14 +22,22 @@ export function isDocumentString(str: any): boolean {
// this why checking the extension is fast enough
// and prevent from parsing the string in order to find out
// if the string is a SDL
if (invalidDocRegex.test(str)) {
if (invalidDocRegex.test(str) || isURL(str)) {
return false;
}

try {
parse(str);
return true;
} catch (e: any) {}
} catch (e: any) {
if (
!e.message.includes('EOF') &&
str.replace(/(\#[^*]*)/g, '').trim() !== '' &&
str.includes(' ')
) {
throw new Error(`Failed to parse the GraphQL document. ${e.message}\n${str}`);
}
}

return false;
}
Expand Down
13 changes: 13 additions & 0 deletions packages/utils/tests/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ describe('helpers', () => {
mutation: Mutation
subscription: Subscription
}`,
/* GraphQL*/ `
extend type Query {
test(id: String!): Test
@resolveTo(
sourceName: "Test"
sourceTypeName: "Test"
sourceFieldName: "test"
requiredSelectionSet: "{ ...on Test { id name } }",
sourceArgs: { testId: {root.id} }
returnType: Test
)
}
`,
])('should detect "%s" as NOT a valid path', str => {
expect(isValidPath(str)).toBeFalsy();
});
Expand Down

0 comments on commit 1e02935

Please sign in to comment.