Skip to content

Commit

Permalink
Support GraphQLID
Browse files Browse the repository at this point in the history
Closes: #187

Summary:

Adds support to specifying a field being of type GraphQLID. Add `format: id` or `format: uuid`.

Test Plan:

1. Change directory to `packages/openapi-to-graphql`
2. Run `npm run start_dev`
3. Browse to localhost:3000/graphql
4. Click on "Docs"
5. Click on "Query"
6. Observe the type of properties whose names end with "id"

Before:

company(id: String!): Company
office(accept: Accept, id: Int!): Office
productWithId(productId: String!, productTag: String!): ProductWithId
productsReviews(id: String!, limit: Int, productTag: String): [ProductsReviewsListItem]

After:

company(id: ID!): Company
office(accept: Accept, id: ID!): Office
productWithId(productId: ID!, productTag: String!): ProductWithId
productsReviews(id: ID!, limit: Int, productTag: String): [ProductsReviewsListItem]

7. Click on "Company"
8. Observe the type of "id"

Before:

id: String
The identifier of a company

After:

id: ID
The identifier of a company

9. Click "Back" twice
10. Click on "Mutation"
11. Click on "ProductWithIdInput"
12. Observe the type of "productId"

Before:

productId: String
The id of the product

After:

productId: ID
The id of the product

Signed-off-by: Omar Chehab <[email protected]>
  • Loading branch information
omarchehab98 authored and ErikWittern committed Aug 7, 2019
1 parent 78feac0 commit e744a45
Show file tree
Hide file tree
Showing 23 changed files with 212 additions and 77 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"test": "cd packages/openapi-to-graphql/ && npm test"
},
"devDependencies": {
"@types/jest": "^24.0.15",
"@types/jest": "^24.0.16",
"graphql": "^14.0.2",
"jest": "^24.8.0",
"lerna": "^3.4.3",
Expand Down
Empty file modified packages/openapi-to-graphql-cli/lib/openapi-to-graphql.js
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions packages/openapi-to-graphql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ Schema options:

- `addLimitArgument` (type: `boolean`, default: `false`): Add a `limit` argument to fields returning lists of objects/lists that will limit the number of returned elements, selecting the first `n` elements of the list.

- `idFormats` (type: `string[]`): If a schema is of type string and has format UUID, it will be translated into a [GraphQL ID type](https://graphql.org/graphql-js/type/#graphqlid). To allow for more customzation, this option allows users to specify other formats that should be interpreted as ID types.

***

Resolver options:
Expand Down
3 changes: 2 additions & 1 deletion packages/openapi-to-graphql/lib/index.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/index.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/lib/oas_3_tools.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export declare function instantiatePathAndGetQuery(path: string, parameters: Par
* Returns the "type" of the given JSON schema. Makes best guesses if the type
* is not explicitly defined.
*/
export declare function getSchemaType(schema: SchemaObject): string | null;
export declare function getSchemaType(schema: SchemaObject, data: PreprocessingData): string | null;
/**
* Determines an approximate name for the resource at the given path.
*/
Expand Down
31 changes: 21 additions & 10 deletions packages/openapi-to-graphql/lib/oas_3_tools.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/oas_3_tools.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/lib/preprocessor.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/preprocessor.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/openapi-to-graphql/lib/schema_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/schema_builder.js.map

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions packages/openapi-to-graphql/lib/types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ export declare type Options = {
* Returns the first n number of elements in the list
*/
addLimitArgument?: boolean;
/**
* If a schema is of type string and has format UUID, it will be translated
* into a GraphQL ID type. To allow for more customzation, this option allows
* users to specify other formats that should be interpreted as ID types.
*/
idFormats?: string[];
/**
* Custom headers to send with every request made by a resolve function.
*/
Expand Down Expand Up @@ -172,6 +178,12 @@ export declare type InternalOptions = {
* Returns the first n number of elements in the list
*/
addLimitArgument: boolean;
/**
* If a schema is of type string and has format UUID, it will be translated
* into a GraphQL ID type. To allow for more customzation, this option allows
* users to specify other formats that should be interpreted as ID types.
*/
idFormats?: string[];
/**
* Custom headers to send with every request made by a resolve function.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/openapi-to-graphql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ async function translateOpenApiToGraphQL(
operationIdFieldNames,
fillEmptyResponses,
addLimitArgument,
idFormats,

// Resolver options
headers,
Expand All @@ -181,6 +182,7 @@ async function translateOpenApiToGraphQL(
operationIdFieldNames,
fillEmptyResponses,
addLimitArgument,
idFormats,

// Resolver options
headers,
Expand Down
40 changes: 27 additions & 13 deletions packages/openapi-to-graphql/src/oas_3_tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import * as Swagger2OpenAPI from 'swagger2openapi'
import * as OASValidator from 'oas-validator'
import debug from 'debug'
import { handleWarning } from './utils'
import { parseType } from 'graphql'

// Type definitions & exports:
export type SchemaNames = {
Expand Down Expand Up @@ -400,14 +399,17 @@ export function instantiatePathAndGetQuery(
* Returns the "type" of the given JSON schema. Makes best guesses if the type
* is not explicitly defined.
*/
export function getSchemaType(schema: SchemaObject): string | null {
export function getSchemaType(
schema: SchemaObject,
data: PreprocessingData
): string | null {
// CASE: enum
if (Array.isArray(schema.enum)) {
return 'enum'
}

// CASE: object
if (schema.type === 'object') {
if (schema.type === 'object' || 'properties' in schema) {
// CASE: arbitrary JSON
if (typeof schema.additionalProperties === 'object') {
return 'json'
Expand All @@ -416,22 +418,34 @@ export function getSchemaType(schema: SchemaObject): string | null {
}
}

if ('properties' in schema) {
return 'object'
}

// CASE: array
if ('items' in schema) {
if (schema.type === 'array' || 'items' in schema) {
return 'array'
}

// CASE: 64 bit int - return number, leading to use of GraphQLFloat:
if (schema.type === 'integer' && schema.format === 'int64') {
return 'number'
}

// CASE: a type is present
if (typeof schema.type === 'string') {
// Special edge cases involving the schema format
if (typeof schema.format === 'string') {
/**
* CASE: 64 bit int - return number instead of integer, leading to use of
* GraphQLFloat, which can support 64 bits:
*/
if (schema.type === 'integer' && schema.format === 'int64') {
return 'number'

// CASE: id
} else if (
schema.type === 'string' &&
(schema.format === 'uuid' ||
// Custom ID format
(Array.isArray(data.options.idFormats) &&
data.options.idFormats.includes(schema.format)))
) {
return 'id'
}
}

return schema.type
}

Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-to-graphql/src/preprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ export function createDataDef(
const saneInputName = Oas3Tools.capitalize(saneName + 'Input')

// Determine the type of the schema
const type = Oas3Tools.getSchemaType(schema as SchemaObject)
const type = Oas3Tools.getSchemaType(schema as SchemaObject, data)
if (!type) {
throw new Error(
`Cannot process schema '${JSON.stringify(
Expand Down
4 changes: 4 additions & 0 deletions packages/openapi-to-graphql/src/schema_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
GraphQLScalarType,
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLInt,
GraphQLFloat,
GraphQLBoolean,
Expand Down Expand Up @@ -378,6 +379,9 @@ function getScalarType({ def, data }: ReuseOrCreateScalar): GraphQLScalarType {
const type = def.type

switch (type) {
case 'id':
def.ot = GraphQLID
break
case 'string':
def.ot = GraphQLString
break
Expand Down
14 changes: 14 additions & 0 deletions packages/openapi-to-graphql/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ export type Options = {
*/
addLimitArgument?: boolean

/**
* If a schema is of type string and has format UUID, it will be translated
* into a GraphQL ID type. To allow for more customzation, this option allows
* users to specify other formats that should be interpreted as ID types.
*/
idFormats?: string[]

// Resolver options

/**
Expand Down Expand Up @@ -202,6 +209,13 @@ export type InternalOptions = {
*/
addLimitArgument: boolean

/**
* If a schema is of type string and has format UUID, it will be translated
* into a GraphQL ID type. To allow for more customzation, this option allows
* users to specify other formats that should be interpreted as ID types.
*/
idFormats?: string[]

// Resolver options

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/openapi-to-graphql/test/docusign.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
/* globals test, expect */

import * as openapiToGraphql from '../lib/index.js'
import { Options } from '../lib/types/options.js'

const oas = require('./fixtures/docusign_oas.json')

test('Generate schema without problems', () => {
const options = {
const options: Options = {
strict: false
}
return openapiToGraphql
Expand Down
Loading

0 comments on commit e744a45

Please sign in to comment.