graphql#parse TypeScript Examples

The following examples show how to use graphql#parse. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: appsync-swift-visitor.test.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
getGQLv2Visitor = (
  schema: string,
  selectedType?: string,
  generate: CodeGenGenerateEnum = CodeGenGenerateEnum.code,
  isTimestampFieldsAdded: boolean = true,
  emitAuthProvider: boolean = true,
  generateIndexRules: boolean = true,
  handleListNullabilityTransparently: boolean = true,
  transformerVersion: number = 2,
) => {
  const ast = parse(schema);
  const builtSchema = buildSchemaWithDirectives(schema);
  const visitor = new AppSyncSwiftVisitor(
    builtSchema,
    {
      directives,
      target: 'swift',
      scalars: SWIFT_SCALAR_MAP,
      isTimestampFieldsAdded,
      emitAuthProvider,
      generateIndexRules,
      handleListNullabilityTransparently,
      transformerVersion: transformerVersion,
    },
    { selectedType, generate },
  );
  visit(ast, { leave: visitor });
  return visitor;
}
Example #2
Source File: example_api.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('Header arguments are not created when they are provided through headers option', () => {
  // The GET snack operation has a snack_type and snack_size header arguments
  const options: Options<any, any, any> = {
    headers: {
      snack_type: 'chips',
      snack_size: 'large',
    },
    fetch,
  };

  const query = `{
    __schema {
      queryType {
        fields {
          name
          args {
            name
          }
        }
      }
    }
  }`;

  return openAPIToGraphQL.createGraphQLSchema(oas, options).then(({ schema }) => {
    const ast = parse(query);
    const errors = validate(schema, ast);
    expect(errors).toEqual([]);
    return graphql({ schema, source: query }).then((result: any) => {
      expect(
        result.data.__schema.queryType.fields.find((field: { name: string }) => {
          return field.name === 'snack';
        })
      ).toEqual({
        name: 'snack',
        args: [], // No arguments
      });
    });
  });
});
Example #3
Source File: codeGeneration.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
function compile(
  source: string,
  options: CompilerOptions = {
    mergeInFieldsFromFragmentSpreads: true,
    addTypename: true,
  }
): CompilerContext {
  const document = parse(source);
  return compileToIR(schema, document, options);
}
Example #4
Source File: example_api.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('Query string arguments are not created when they are provided through qs option', () => {
  // The GET status operation has a limit query string parameter
  const options: Options<any, any, any> = {
    qs: {
      limit: '10',
    },
    fetch,
  };

  const query = `{
    __schema {
      queryType {
        fields {
          name
          args {
            name
          }
        }
      }
    }
  }`;

  return openAPIToGraphQL.createGraphQLSchema(oas, options).then(({ schema }) => {
    const ast = parse(query);
    const errors = validate(schema, ast);
    expect(errors).toEqual([]);
    return graphql({ schema, source: query }).then((result: any) => {
      expect(
        result.data.__schema.queryType.fields.find((field: { name: string }) => {
          return field.name === 'users';
        })
      ).toEqual({
        name: 'users',
        args: [], // No arguments
      });
    });
  });
});
Example #5
Source File: loading.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
export function loadAndMergeQueryDocuments(inputPaths: string[], tagName: string = 'gql'): DocumentNode {
  const sources = inputPaths
    .map(inputPath => {
      const body = fs.readFileSync(inputPath, 'utf8');
      if (!body) {
        return null;
      }
      return new Source(body, inputPath);
    })
    .filter(source => source);

  return concatAST((sources as Source[]).map(source => parse(source)));
}
Example #6
Source File: example_api.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('Non-nullable properties from nested allOf', () => {
  // Check query/mutation field descriptions
  const query = `{
    __type(name: "Nomenclature") {
      fields {
        name
        type {
          kind
          ofType {
            name
            kind
          }
        }
      }
    }
  }`;

  return openAPIToGraphQL.createGraphQLSchema(oas, { fetch }).then(({ schema }) => {
    const ast = parse(query);
    const errors = validate(schema, ast);
    expect(errors).toEqual([]);
    return graphql({ schema, source: query }).then((result: any) => {
      expect(
        result.data.__type.fields.find((field: { name: string }) => {
          return field.name === 'family';
        })
      ).toEqual({
        name: 'family',
        type: {
          kind: 'NON_NULL',
          ofType: {
            name: 'String',
            kind: 'SCALAR',
          },
        },
      });
    });
  });
});
Example #7
Source File: appsync-visitor.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
constructor(
    protected _schema: GraphQLSchema,
    rawConfig: TRawConfig,
    additionalConfig: Partial<TPluginConfig>,
    defaultScalars: NormalizedScalarsMap = DEFAULT_SCALARS,
  ) {
    super(rawConfig, {
      ...additionalConfig,
      scalars: buildScalars(_schema, rawConfig.scalars || '', defaultScalars),
      target: rawConfig.target,
      isTimestampFieldsAdded: rawConfig.isTimestampFieldsAdded,
      handleListNullabilityTransparently: rawConfig.handleListNullabilityTransparently,
      usePipelinedTransformer: rawConfig.usePipelinedTransformer,
      transformerVersion: rawConfig.transformerVersion,
    });

    const typesUsedInDirectives: string[] = [];
    if (rawConfig.directives) {
      const directiveSchema = parse(rawConfig.directives);
      directiveSchema.definitions.forEach((definition: DefinitionNode) => {
        if (definition.kind === Kind.ENUM_TYPE_DEFINITION || definition.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION) {
          typesUsedInDirectives.push(definition.name.value);
        }
      });
    }

    this.typesToSkip = [this._schema.getQueryType(), this._schema.getMutationType(), this._schema.getSubscriptionType()]
      .filter(t => t)
      .map(t => (t && t.name) || '');
    this.typesToSkip.push(...typesUsedInDirectives);
  }
Example #8
Source File: example_api_combined.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('addLimitArgument and allOf', () => {
  const options: Options<any, any, any> = {
    addLimitArgument: true,
    fetch,
  };

  const query = `query {
    cars(limit: 1) {
      model
    }
  }`;

  return openAPIToGraphQL.createGraphQLSchema(oas, options).then(({ schema }) => {
    const ast = parse(query);
    const errors = validate(schema, ast);
    expect(errors).toEqual([]);
    return graphql({ schema, source: query }).then((result: any) => {
      expect(result.data.cars.length).toEqual(1);
    });
  });
});
Example #9
Source File: appsync-javascript-visitor.test.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
getGQLv2Visitor = (
  schema: string,
  selectedType?: string,
  isDeclaration: boolean = false,
  generate: CodeGenGenerateEnum = CodeGenGenerateEnum.code,
  isTimestampFieldsAdded: boolean = false,
): AppSyncModelJavascriptVisitor => {
  const ast = parse(schema);
  const builtSchema = buildSchemaWithDirectives(schema);
  const visitor = new AppSyncModelJavascriptVisitor(
    builtSchema,
    { directives, target: 'javascript', scalars: TYPESCRIPT_SCALAR_MAP, isDeclaration, isTimestampFieldsAdded, transformerVersion: 2 },
    { selectedType, generate },
  );
  visit(ast, { leave: visitor });
  return visitor;
}
Example #10
Source File: cloudfunction.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
describe('Cloudfunction', () => {
  let createdSchema: GraphQLSchema;
  beforeAll(async () => {
    createdSchema = await loadGraphQLSchemaFromOpenAPI('test', {
      oasFilePath: join(__dirname, '../../../handlers/openapi/test/fixtures/cloudfunction.json'),
      operationHeaders: {
        Authorization: 'Basic {args.usernamePassword|base64}',
      },
      ignoreErrorResponses: true, // Because Error type is invalid in the OAS file
    });
  });
  it('should generate correct schema', () => {
    expect(printSchemaWithDirectives(createdSchema)).toMatchSnapshot('cloudfunction-schema');
  });
  it('should validate the following query', () => {
    const query = /* GraphQL */ `
      mutation {
        post_test_action_2(input: { age: 27 }, usernamePassword: "test:data") {
          payload
          age
        }
      }
    `;
    const document = parse(query);
    const errors = validate(createdSchema, document);
    expect(errors).toEqual([]);
  });
});
Example #11
Source File: appsync-dart-visitor.test.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
getGQLv2Visitor = (
  schema: string,
  selectedType?: string,
  generate: CodeGenGenerateEnum = CodeGenGenerateEnum.code,
  enableDartNullSafety: boolean = true,
) => {
  const ast = parse(schema);
  const builtSchema = buildSchemaWithDirectives(schema);
  const visitor = new AppSyncModelDartVisitor(
    builtSchema,
    { directives, target: 'dart', scalars: DART_SCALAR_MAP, enableDartNullSafety, transformerVersion: 2 },
    { selectedType, generate },
  );
  visit(ast, { leave: visitor });
  return visitor;
}
Example #12
Source File: example_api_combined.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
describe('Example API Combined', () => {
  let createdSchema: GraphQLSchema;
  beforeAll(async () => {
    await startServer(PORT);
    createdSchema = await loadGraphQLSchemaFromOpenAPI('test', {
      oasFilePath,
      baseUrl,
      fetch,
    });
  });
  afterAll(async () => {
    await stopServer();
  });
  it('should generate correct schema', () => {
    expect(printSchemaWithDirectives(createdSchema)).toMatchSnapshot('example_oas_combined-schema');
  });
  it('should handle allOf correctly', async () => {
    const query = /* GraphQL */ `
      query {
        getAllCars {
          model
        }
      }
    `;
    const result = await execute({
      schema: createdSchema,
      document: parse(query),
    });
    expect(result).toMatchSnapshot('example_oas_combined-query-result');
  });
});
Example #13
Source File: appsync-visitor.test.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
createAndGenerateVisitor = (schema: string, usePipelinedTransformer: boolean = false) => {
  const ast = parse(schema);
  const builtSchema = buildSchemaWithDirectives(schema);
  const visitor = new AppSyncModelVisitor(
    builtSchema,
    { directives, target: 'general', isTimestampFieldsAdded: true, usePipelinedTransformer: usePipelinedTransformer },
    { generate: CodeGenGenerateEnum.code },
  );
  visit(ast, { leave: visitor });
  visitor.generate();
  return visitor;
}
Example #14
Source File: tools.ts    From squid with GNU General Public License v3.0 6 votes vote down vote up
export function loadModel(schemaFile: string): Model {
    let files: string[] = []
    if (fs.statSync(schemaFile).isDirectory()) {
        fs.readdirSync(schemaFile, {withFileTypes: true}).forEach(item => {
            if (item.isFile() && (item.name.endsWith('.graphql') || item.name.endsWith('.gql'))) {
                files.push(path.join(schemaFile, item.name))
            }
        })
    } else {
        files.push(schemaFile)
    }

    let docs = files.map(f => {
        let src = new Source(
            fs.readFileSync(f, 'utf-8'),
            f
        )
        return parse(src)
    })

    if (docs.length == 0) return {}
    let doc = docs.length == 1 ? docs[0] : mergeTypeDefs(docs)
    let schema = buildSchema(doc)
    return buildModel(schema)
}
Example #15
Source File: operation.test.ts    From apollo-link-sentry with MIT License 6 votes vote down vote up
export function makeOperation(overwrites: Partial<Operation> = {}): Operation {
  return {
    query: parse(`query Foo { foo }`),
    operationName: 'Foo',
    variables: {},
    extensions: {},
    getContext: () => ({}),
    setContext: (context) => context,

    ...overwrites,
  };
}
Example #16
Source File: schema.ts    From squid with GNU General Public License v3.0 6 votes vote down vote up
baseSchema = buildASTSchema(parse(`
    directive @entity on OBJECT
    directive @derivedFrom(field: String!) on FIELD_DEFINITION
    directive @unique on FIELD_DEFINITION
    directive @index(fields: [String!] unique: Boolean) on OBJECT | FIELD_DEFINITION
    directive @fulltext(query: String!) on FIELD_DEFINITION
    directive @variant on OBJECT # legacy
    directive @jsonField on OBJECT # legacy
    scalar ID
    ${Object.keys(customScalars).map(name => 'scalar ' + name).join('\n')}
`))
Example #17
Source File: parseAndPrintWithCache.ts    From graphql-mesh with MIT License 6 votes vote down vote up
export function parseWithCache(sdl: string): DocumentNode {
  const trimmedSdl = sdl.trim();
  let document: DocumentNode = parseCache.get(trimmedSdl);
  if (!document) {
    document = parse(trimmedSdl, { noLocation: true });
    parseCache.set(trimmedSdl, document);
    printCache.set(JSON.stringify(document), trimmedSdl);
  }
  return document;
}
Example #18
Source File: resolvers.ts    From squid with GNU General Public License v3.0 6 votes vote down vote up
export async function loadCustomResolvers(mod: string): Promise<CustomResolvers> {
    let {typeDefs, resolvers} = await buildTypeDefsAndResolvers({
        resolvers: [mod],
        scalarsMap: [
            { type: Date, scalar: DateTime },
            { type: BigInt, scalar: BigInteger },
            { type: Buffer, scalar: Bytes }
        ],
        container: resolverData => new CustomResolversContainer(resolverData)
    })
    return {
        resolvers,
        typeDefs: parse(typeDefs)
    }
}
Example #19
Source File: federation.ts    From graphql-schema-registry with MIT License 6 votes vote down vote up
export function composeAndValidateSchema(servicesSchemaMap) {
	let schema;
	let errors = [];

	try {
		const serviceList = servicesSchemaMap.map((schema) => {
			const typeDefs = parse(schema.type_defs);

			return {
				name: schema.name,
				url: schema.url,
				typeDefs,
			};
		});

		({ schema, errors } = composeAndValidate(serviceList));
	} catch (error) {
		logger.error(error.message);

		errors = [error];
	}

	if (errors && errors.length) {
		throw new PublicError('Schema validation failed', {
			details: errors,
		});
	}

	return schema;
}
Example #20
Source File: buildGqlQuery.ts    From ra-data-prisma with MIT License 6 votes vote down vote up
buildFieldsFromFragment = (
  fragment: DocumentNode | string,
  resourceName: string,
  fetchType: string,
): SelectionNode[] => {
  let parsedFragment = {};

  if (
    typeof fragment === "object" &&
    fragment.kind &&
    fragment.kind === "Document"
  ) {
    parsedFragment = fragment;
  }

  if (typeof fragment === "string") {
    if (!fragment.startsWith("fragment")) {
      fragment = `fragment tmp on ${resourceName} ${fragment}`;
    }

    try {
      parsedFragment = parse(fragment);
    } catch (e) {
      throw new Error(
        `Invalid fragment given for resource '${resourceName}' and fetchType '${fetchType}' (${e.message}).`,
      );
    }
  }

  return (parsedFragment as any).definitions?.[0].selectionSet.selections;
}
Example #21
Source File: cloudfunction.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('Get response', async () => {
  const query = `mutation {
    mutationViewerBasicAuth (username: "test" password: "data") {
      postTestAction2 (payloadInput: {age: 27}) {
        payload
        age
      }
    }
  }`;
  // validate that 'limit' parameter is covered by options:
  const ast = parse(query);
  const errors = validate(createdSchema, ast);
  expect(errors).toEqual([]);
});
Example #22
Source File: index.test.ts    From mercurius-typescript with MIT License 6 votes vote down vote up
test('gql helper', (t) => {
  t.plan(2)

  const a = gql`
    query A {
      hello
    }
  `

  const b = gql`
    query B {
      hello
    }
    ${a}
  `

  t.snapshot(print(parse(a)))
  t.snapshot(print(parse(b)))
})
Example #23
Source File: example_api.test.ts    From graphql-mesh with MIT License 6 votes vote down vote up
test('Option customResolver using resolver arguments', () => {
  const options: Options<any, any, any> = {
    customResolvers: {
      'Example API': {
        '/users/{username}': {
          get: (obj, args: any, context, info) => {
            return {
              name: args.username,
            };
          },
        },
      },
    },
    fetch,
  };

  const query = `query {
    user(username: "abcdef") {
      name
    }
  }`;

  return openAPIToGraphQL.createGraphQLSchema(oas, options).then(({ schema }) => {
    const ast = parse(query);
    const errors = validate(schema, ast);
    expect(errors).toEqual([]);
    return graphql({ schema, source: query }).then((result: any) => {
      expect(result).toEqual({
        data: {
          user: {
            name: 'abcdef',
          },
        },
      });
    });
  });
});
Example #24
Source File: appsync-dart-visitor.test.ts    From amplify-codegen with Apache License 2.0 6 votes vote down vote up
getVisitor = ({
  schema,
  selectedType,
  generate = CodeGenGenerateEnum.code,
  enableDartNullSafety = false,
  enableDartZeroThreeFeatures = false,
  isTimestampFieldsAdded = false,
  transformerVersion = 1,
  dartUpdateAmplifyCoreDependency = false
}: {
  schema: string;
  selectedType?: string;
  generate?: CodeGenGenerateEnum;
  enableDartNullSafety?: boolean;
  enableDartZeroThreeFeatures?: boolean;
  isTimestampFieldsAdded?: boolean;
  transformerVersion?: number;
  dartUpdateAmplifyCoreDependency?: boolean;
}) => {
  const ast = parse(schema);
  const builtSchema = buildSchemaWithDirectives(schema);
  const visitor = new AppSyncModelDartVisitor(
    builtSchema,
    {
      directives,
      target: 'dart',
      scalars: DART_SCALAR_MAP,
      enableDartNullSafety,
      enableDartZeroThreeFeatures,
      isTimestampFieldsAdded,
      transformerVersion,
      dartUpdateAmplifyCoreDependency
    },
    { selectedType, generate },
  );
  visit(ast, { leave: visitor });
  return visitor;
}
Example #25
Source File: transform.spec.ts    From graphql-mesh with MIT License 5 votes vote down vote up
describe('transform', () => {
  const baseDir: string = undefined;

  it('should handle composition functions from external modules', async () => {
    const transform = new ResolversCompositionTransform({
      cache: new InMemoryLRUCache(),
      pubsub: new PubSub(),
      config: [
        {
          resolver: 'Query.foo',
          composer: join(__dirname, './fixtures/composer.js'),
        },
      ],
      baseDir,
      apiName: '',
      importFn: m => import(m),
    });
    const schema = makeExecutableSchema({
      typeDefs: /* GraphQL */ `
        type Query {
          foo: String
        }
      `,
      resolvers: {
        Query: {
          foo: () => 'BAR',
        },
      },
    });
    const transformedSchema = transform.transformSchema(schema);
    const result = await execute({
      schema: transformedSchema,
      document: parse(/* GraphQL */ `
        {
          foo
        }
      `),
    });
    expect(result.data?.foo).toBe('FOO');
  });
  it('should handle composition functions from functions', async () => {
    const composer: ResolversComposition = next => (root, args, context, info) => 'FOO';
    const transform = new ResolversCompositionTransform({
      cache: new InMemoryLRUCache(),
      pubsub: new PubSub(),
      config: [
        {
          resolver: 'Query.foo',
          composer,
        },
      ],
      baseDir,
      apiName: '',
      importFn: m => import(m),
    });
    const schema = makeExecutableSchema({
      typeDefs: /* GraphQL */ `
        type Query {
          foo: String
        }
      `,
      resolvers: {
        Query: {
          foo: () => 'BAR',
        },
      },
    });
    const transformedSchema = transform.transformSchema(schema);
    const result = await execute({
      schema: transformedSchema,
      document: parse(/* GraphQL */ `
        {
          foo
        }
      `),
    });
    expect(result.data?.foo).toBe('FOO');
  });
});
Example #26
Source File: faderation-factory.util.ts    From nestjs-mercurius with MIT License 5 votes vote down vote up
/**
 * Inspired by https://github.com/mercurius-js/mercurius/blob/master/lib/federation.js#L231
 * Accept a GraphQLSchema to transform instead of a plain string containing a graphql schema
 * @param schema
 */
export function transformFederatedSchema(schema: GraphQLSchema) {
  // FIXME remove this dependency
  // but graphql#printSchema does not print necessary federation directives
  const { printSubgraphSchema } = loadPackage(
    '@apollo/subgraph',
    'FederationFactory',
    () => require('@apollo/subgraph'),
  );

  // Workaround for https://github.com/mercurius-js/mercurius/issues/273
  const schemaString = printSubgraphSchema(schema)
    .replace('type Query {', 'type Query @extends {')
    .replace('type Mutation {', 'type Mutation @extends {')
    .replace('type Subscription {', 'type Subscription @extends {');

  schema = extendSchema(schema, parse(FEDERATION_SCHEMA), {
    assumeValidSDL: true,
  });

  if (!schema.getType('Query')) {
    schema = new GraphQLSchema({
      ...schema.toConfig(),
      query: new GraphQLObjectType({
        name: 'Query',
        fields: {},
      }),
    });
  }

  schema = extendSchema(
    schema,
    parse(`
    extend type Query {
      _service: _Service!
    }
  `),
    {
      assumeValid: true,
    },
  );

  const query = schema.getType('Query') as GraphQLObjectType;
  const queryFields = query.getFields();

  queryFields._service = {
    ...queryFields._service,
    resolve: () => ({ sdl: schemaString }),
  };

  const entityTypes = Object.values(schema.getTypeMap()).filter(
    (type) => isObjectType(type) && typeIncludesDirective(type, 'key'),
  );

  if (entityTypes.length > 0) {
    schema = extendSchema(
      schema,
      parse(`
      union _Entity = ${entityTypes.join(' | ')}
      extend type Query {
        _entities(representations: [_Any!]!): [_Entity]!
      }
    `),
      {
        assumeValid: true,
      },
    );

    const query = schema.getType('Query') as GraphQLObjectType;
    const queryFields = query.getFields();
    queryFields._entities = {
      ...queryFields._entities,
      resolve: (_source, { representations }, context, info) => {
        return representations.map((reference) => {
          const { __typename } = reference;

          const type = info.schema.getType(__typename);
          if (!type || !isObjectType(type)) {
            throw new MER_ERR_GQL_GATEWAY_INVALID_SCHEMA(__typename);
          }

          const resolveReference = (type as any).resolveReference
            ? (type as any).resolveReference
            : function defaultResolveReference() {
                return reference;
              };

          const result = resolveReference(reference, {}, context, info);

          if (result && 'then' in result && typeof result.then === 'function') {
            return result.then((x) => addTypeNameToResult(x, __typename));
          }

          return addTypeNameToResult(result, __typename);
        });
      },
    };
  }

  return schema;
}
Example #27
Source File: plugin.ts    From amplify-codegen with Apache License 2.0 5 votes vote down vote up
plugin: PluginFunction<RawAppSyncModelConfig> = (
  schema: GraphQLSchema,
  rawDocuments: Types.DocumentFile[],
  config: RawAppSyncModelConfig,
) => {
  let visitor;
  switch (config.target) {
    case 'swift':
      visitor = new AppSyncSwiftVisitor(schema, config, {
        selectedType: config.selectedType,
        generate: config.generate,
      });
      break;
    case 'java':
      visitor = new AppSyncModelJavaVisitor(schema, config, {
        selectedType: config.selectedType,
        generate: config.generate,
      });
      break;
    case 'metadata':
      visitor = new AppSyncJSONVisitor(schema, config, {});
      break;
    case 'typescript':
      visitor = new AppSyncModelTypeScriptVisitor(schema, config, {});
      break;
    case 'javascript':
      visitor = new AppSyncModelJavascriptVisitor(schema, config, {});
      break;
    case 'dart':
      visitor = new AppSyncModelDartVisitor(schema, config, {
        selectedType: config.selectedType,
        generate: config.generate,
      });
      break;
    default:
      return '';
  }
  if (schema) {
    const schemaStr = printSchemaWithDirectives(schema);
    const node = parse(schemaStr);
    visit(node, {
      leave: visitor,
    });
    return visitor.generate();
  }
  return '';
}
Example #28
Source File: handler.ts    From graphql-sse with MIT License 5 votes vote down vote up
async function parseReq<Request extends IncomingMessage>(
  req: Request,
  body: unknown,
): Promise<RequestParams> {
  const params: Partial<RequestParams> = {};

  if (req.method === 'GET') {
    await new Promise<void>((resolve, reject) => {
      try {
        const url = new URL(req.url ?? '', 'http://localhost/');
        params.operationName =
          url.searchParams.get('operationName') ?? undefined;
        params.query = url.searchParams.get('query') ?? undefined;
        const variables = url.searchParams.get('variables');
        if (variables) params.variables = JSON.parse(variables);
        const extensions = url.searchParams.get('extensions');
        if (extensions) params.extensions = JSON.parse(extensions);
        resolve();
      } catch {
        reject(new Error('Unparsable URL'));
      }
    });
  } else if (req.method === 'POST') {
    await new Promise<void>((resolve, reject) => {
      const end = (body: Record<string, unknown> | string) => {
        try {
          const data = typeof body === 'string' ? JSON.parse(body) : body;
          params.operationName = data.operationName;
          params.query = data.query;
          params.variables = data.variables;
          params.extensions = data.extensions;
          resolve();
        } catch {
          reject(new Error('Unparsable body'));
        }
      };
      if (typeof body === 'string' || isObject(body)) end(body);
      else {
        let body = '';
        req.on('data', (chunk) => (body += chunk));
        req.on('end', () => end(body));
      }
    });
  } else throw new Error(`Unsupported method ${req.method}`); // should never happen

  if (!params.query) throw new Error('Missing query');
  if (params.variables && typeof params.variables !== 'object')
    throw new Error('Invalid variables');
  if (params.extensions && typeof params.extensions !== 'object')
    throw new Error('Invalid extensions');

  return params as RequestParams;
}
Example #29
Source File: index.ts    From hono with MIT License 5 votes vote down vote up
getGraphQLParams = async (request: Request): Promise<GraphQLParams> => {
  const urlData = new URLSearchParams(request.url.split('?')[1])
  const bodyData = await parseBody(request)

  // GraphQL Query string.
  let query = urlData.get('query') ?? (bodyData.query as string | null)

  if (typeof query !== 'string') {
    query = null
  }

  // Parse the variables if needed.
  let variables = (urlData.get('variables') ?? bodyData.variables) as {
    readonly [name: string]: unknown
  } | null
  if (typeof variables === 'string') {
    try {
      variables = JSON.parse(variables)
    } catch {
      throw Error('Variables are invalid JSON.')
    }
  } else if (typeof variables !== 'object') {
    variables = null
  }

  // Name of GraphQL operation to execute.
  let operationName = urlData.get('operationName') ?? (bodyData.operationName as string | null)
  if (typeof operationName !== 'string') {
    operationName = null
  }

  const raw = urlData.get('raw') != null || bodyData.raw !== undefined

  const params: GraphQLParams = {
    query: query,
    variables: variables,
    operationName: operationName,
    raw: raw,
  }

  return params
}