Skip to content

Commit

Permalink
requestOptions accepting function so that we can change options depen…
Browse files Browse the repository at this point in the history
…ding on the request
  • Loading branch information
dinumathai committed Mar 24, 2021
1 parent 784b89a commit fa6f0ac
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ Resolver options:

- `qs` (type: `object`, default: `{}`): Query parameters to be sent in every request to the API. Parameters defined in the OpenAPI Specification and set by these query parameters will be ignored by OpenAPI-to-GraphQL.

- `requestOptions` (type: `object`, default: `{}`): Additional [options](https://github.com/request/request#requestoptions-callback), provided by the [`Request` module](https://github.com/request/request), that can be used to configure the HTTP calls that powers the generated GraphQL resolvers. A common use case for this option is to set up a web proxy with the `proxy` field. Parameters defined in the OpenAPI Specification and set by this option will be ignored by OpenAPI-to-GraphQL. Additionally, the `headers` field has the feature of being used as a function. If used as a function, the following parameters will be exposed per-request: the operation's `method`, the operation's `path`, the API `title`, and `resolverParams` (the [GraphQL resolver's parameters](https://graphql.org/learn/execution/#root-fields-resolvers)). The function should return the desired headers.
- `requestOptions` (type: `object` | `function`, default: `{}`): Additional [options](https://github.com/request/request#requestoptions-callback), provided by the [`Request` module](https://github.com/request/request), that can be used to configure the HTTP calls that powers the generated GraphQL resolvers. A common use case for this option is to set up a web proxy with the `proxy` field. Parameters defined in the OpenAPI Specification and set by this option will be ignored by OpenAPI-to-GraphQL. Additionally, the `headers` field has the feature of being used as a function. If used as a function, the following parameters will be exposed per-request: the operation's `method`, the operation's `path`, the API `title`, and `resolverParams` (the [GraphQL resolver's parameters](https://graphql.org/learn/execution/#root-fields-resolvers)). The function should return the desired headers. If `requestOptions` is used as a function, the following parameters will be exposed per-request: the operation's `method`, the operation's `path`, the API `title`, and `resolverParams` (the [GraphQL resolver's parameters](https://graphql.org/learn/execution/#root-fields-resolvers)). It should return object of type [options](https://github.com/request/request#requestoptions-callback). If `requestOptions` is used as a function `url` and `method` can also be set.

- `baseUrl` (type: `string`): Used to manually specify the base URL which all paths will be built on. Normally, OpenAPI-to-GraphQL will select a base URL from the [server object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#serverObject) defined in the OAS. However, if the server object contains multiple URLs, OpenAPI-to-GraphQL will randomly select one. The purpose of this option is to provide greater control over the base URL in these situations, especially when the OAS cannot be modified. This option may also prove to be useful in testing and development.

Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/lib/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/openapi-to-graphql/lib/resolver_builder.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ConnectOptions } from './types/options';
import { Operation } from './types/operation';
import { SubscriptionContext } from './types/graphql';
import { PreprocessingData } from './types/preprocessing_data';
import { RequestOptions } from './types/options';
import { RequestOptions, RequestOptionsFunction } from './types/options';
import { GraphQLFieldResolver } from 'graphql';
import { IncomingHttpHeaders } from 'http';
export declare const OPENAPI_TO_GRAPHQL = "_openAPIToGraphQL";
Expand All @@ -20,7 +20,7 @@ declare type GetResolverParams<TSource, TContext, TArgs> = {
responseName?: string;
data: PreprocessingData<TSource, TContext, TArgs>;
baseUrl?: string;
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>>;
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>> | RequestOptionsFunction<TSource, TContext, TArgs>;
};
declare type GetSubscribeParams<TSource, TContext, TArgs> = {
operation: Operation;
Expand Down
34 changes: 25 additions & 9 deletions packages/openapi-to-graphql/lib/resolver_builder.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/lib/resolver_builder.js.map

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion packages/openapi-to-graphql/lib/types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export declare type RequestHeadersFunction<TSource, TContext, TArgs> = (method:
context: TContext;
info: GraphQLResolveInfo;
}) => Headers;
export declare type RequestOptionsFunction<TSource, TContext, TArgs> = (method: string, path: string, title: string, resolverParams?: {
source: TSource;
args: TArgs;
context: TContext;
info: GraphQLResolveInfo;
}) => Partial<NodeRequest.CoreOptions>;
/**
* We rely on the Request library in order to make resolver API calls.
*
Expand Down Expand Up @@ -175,7 +181,7 @@ export declare type InternalOptions<TSource, TContext, TArgs> = {
*
* Based on: https://github.com/request/request#requestoptions-callback
*/
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>>;
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>> | RequestOptionsFunction<TSource, TContext, TArgs>;
/**
* Allows to override or add options to the PubSub connect object used to make
* publish/subscribe to the API backend.
Expand Down
5 changes: 4 additions & 1 deletion packages/openapi-to-graphql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
InternalOptions,
Report,
ConnectOptions,
RequestOptionsFunction,
RequestOptions
} from './types/options'
import { Oas3 } from './types/oas3'
Expand Down Expand Up @@ -640,7 +641,9 @@ function getFieldForOperation<TSource, TContext, TArgs>(
operation: Operation,
baseUrl: string,
data: PreprocessingData<TSource, TContext, TArgs>,
requestOptions: Partial<RequestOptions<TSource, TContext, TArgs>>,
requestOptions:
| Partial<RequestOptions<TSource, TContext, TArgs>>
| RequestOptionsFunction<TSource, TContext, TArgs>,
connectOptions: ConnectOptions
): GraphQLFieldConfig<TSource, TContext | SubscriptionContext, TArgs> {
// Create GraphQL Type for response:
Expand Down
46 changes: 34 additions & 12 deletions packages/openapi-to-graphql/src/resolver_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Operation } from './types/operation'
import { SubscriptionContext } from './types/graphql'
import { PreprocessingData } from './types/preprocessing_data'
import * as NodeRequest from 'request'
import { RequestOptions } from './types/options'
import { RequestOptions, RequestOptionsFunction } from './types/options'

// Imports:
import * as Oas3Tools from './oas_3_tools'
Expand Down Expand Up @@ -57,7 +57,9 @@ type GetResolverParams<TSource, TContext, TArgs> = {
responseName?: string
data: PreprocessingData<TSource, TContext, TArgs>
baseUrl?: string
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>>
requestOptions?:
| Partial<RequestOptions<TSource, TContext, TArgs>>
| RequestOptionsFunction<TSource, TContext, TArgs>
}

type GetSubscribeParams<TSource, TContext, TArgs> = {
Expand Down Expand Up @@ -487,7 +489,7 @@ export function getResolver<TSource, TContext, TArgs>({
args,
data
)
const url = baseUrl + path
let url = baseUrl + path

/**
* The Content-Type and Accept property should not be changed because the
Expand All @@ -510,21 +512,41 @@ export function getResolver<TSource, TContext, TArgs>({

let options: NodeRequest.OptionsWithUrl
if (requestOptions) {
let requestOptionsVal: any = requestOptions
let method = operation.method
if (typeof requestOptions === 'function') {
requestOptionsVal = requestOptions(method, path, title, {
source,
args,
context,
info
})

if (
requestOptionsVal.url &&
requestOptionsVal.url.toString().trim().length > 0
) {
url = requestOptionsVal.url.toString().trim()
}
if (requestOptionsVal.method && requestOptionsVal.method.length > 0) {
method = Oas3Tools.methodToHttpMethod(requestOptionsVal.method)
}
}
options = {
...requestOptions,
method: operation.method,
...requestOptionsVal,
method: method,
url // Must be after the requestOptions spread as url is a mandatory field so undefined may be used
}

options.headers = {} // Handle requestOptions.header later if applicable
options.qs = {} // Handle requestOptions.qs later if applicable

if (requestOptions.headers) {
if (requestOptionsVal.headers) {
// requestOptions.headers may be either an object or a function
if (typeof requestOptions.headers === 'object') {
Object.assign(options.headers, headers, requestOptions.headers)
} else if (typeof requestOptions.headers === 'function') {
const headers = requestOptions.headers(method, path, title, {
if (typeof requestOptionsVal.headers === 'object') {
Object.assign(options.headers, headers, requestOptionsVal.headers)
} else if (typeof requestOptionsVal.headers === 'function') {
const headers = requestOptionsVal.headers(method, path, title, {
source,
args,
context,
Expand All @@ -539,8 +561,8 @@ export function getResolver<TSource, TContext, TArgs>({
options.headers = headers
}

if (requestOptions.qs) {
Object.assign(options.qs, qs, requestOptions.qs)
if (requestOptionsVal.qs) {
Object.assign(options.qs, qs, requestOptionsVal.qs)
} else {
options.qs = qs
}
Expand Down
16 changes: 15 additions & 1 deletion packages/openapi-to-graphql/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ export type RequestHeadersFunction<TSource, TContext, TArgs> = (
}
) => Headers

export type RequestOptionsFunction<TSource, TContext, TArgs> = (
method: string,
path: string,
title: string,
resolverParams?: {
source: TSource
args: TArgs
context: TContext
info: GraphQLResolveInfo
}
) => Partial<NodeRequest.CoreOptions>

/**
* We rely on the Request library in order to make resolver API calls.
*
Expand Down Expand Up @@ -219,7 +231,9 @@ export type InternalOptions<TSource, TContext, TArgs> = {
*
* Based on: https://github.com/request/request#requestoptions-callback
*/
requestOptions?: Partial<RequestOptions<TSource, TContext, TArgs>>
requestOptions?:
| Partial<RequestOptions<TSource, TContext, TArgs>>
| RequestOptionsFunction<TSource, TContext, TArgs>

/**
* Allows to override or add options to the PubSub connect object used to make
Expand Down

0 comments on commit fa6f0ac

Please sign in to comment.