fix request and response transform generate by import from OpenAPI wh…

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9705
GitOrigin-RevId: 63c4467072d842b11fca8e0a8140b44464c4bc65
This commit is contained in:
Daniele Cammareri 2023-07-05 13:33:36 +02:00 committed by hasura-bot
parent fdcd4748a6
commit af51a481c2
6 changed files with 513 additions and 5 deletions

View File

@ -5,7 +5,7 @@ import { handlers } from '../../../../mocks/metadata.mock';
import { within, userEvent } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
import { OASGenerator, OASGeneratorProps } from './OASGenerator';
import petstore from './petstore.json';
import petstore from './fixtures/petstore.json';
const meta = {
title: 'Features/Actions/OASGenerator',

View File

@ -0,0 +1,147 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`optimizer API should generate correctly 1`] = `
{
"action": "type Mutation {
optimiseOptimisePost(optimiserRequestInput: OptimiserRequestInput!): OptimiserResponse
}
",
"actionType": "mutation",
"baseUrl": "",
"description": "",
"headers": [],
"method": "POST",
"operationId": "optimise_optimise_post",
"path": "/optimise",
"queryParams": [],
"requestTransforms": {
"type": "json",
"value": "{
"gene_name": {{$body.input.optimiserRequestInput?['geneName']}},
"sequence": {{$body.input.optimiserRequestInput?['sequence']}},
"score": {{$body.input.optimiserRequestInput?['score']}},
"optimise": {{$body.input.optimiserRequestInput?['optimise']}},
"features": {{if inverse(empty($body.input.optimiserRequestInput?['features']))}} {{ range _, features := $body.input.optimiserRequestInput?['features']}} {
"name": {{features?['name']}},
"feature_type": {{features?['featureType']}},
"start": {{features?['start']}},
"end": {{features?['end']}},
"optimise": {{features?['optimise']}}
} {{end}} {{else}} null {{end}},
"optimisation_params": {{$body.input.optimiserRequestInput?['optimisationParams']}},
"from_json": {{$body.input.optimiserRequestInput?['fromJson']}},
"to_json": {{$body.input.optimiserRequestInput?['toJson']}}
}",
},
"responseTransforms": "{
"geneName": {{$body?['gene_name']}},
"preOptimisationSequence": {{$body?['pre_optimisation_sequence']}},
"postOptimisationSequence": {{$body?['post_optimisation_sequence']}},
"preOptimisationPenalties": {{if inverse(empty($body?['pre_optimisation_penalties']))}} {{ range _, preOptimisationPenalties := $body?['pre_optimisation_penalties']}} {
"start": {{pre_optimisation_penalties?['start']}},
"end": {{pre_optimisation_penalties?['end']}},
"group": {{pre_optimisation_penalties?['group']}},
"score": {{pre_optimisation_penalties?['score']}},
"strand": {{pre_optimisation_penalties?['strand']}}
} {{end}} {{else}} null {{end}},
"preOptimisationScoreDetail": {{$body?['pre_optimisation_score_detail']}},
"postOptimisationPenalties": {{if inverse(empty($body?['post_optimisation_penalties']))}} {{ range _, postOptimisationPenalties := $body?['post_optimisation_penalties']}} {
"start": {{post_optimisation_penalties?['start']}},
"end": {{post_optimisation_penalties?['end']}},
"group": {{post_optimisation_penalties?['group']}},
"score": {{post_optimisation_penalties?['score']}},
"strand": {{post_optimisation_penalties?['strand']}}
} {{end}} {{else}} null {{end}},
"postOptimisationScoreDetail": {{$body?['post_optimisation_score_detail']}}
}",
"sampleInput": "{
"action": {
"name": "optimiseOptimisePost"
},
"input": {
"optimiserRequestInput": {
"fromJson": false,
"geneName": "geneName",
"optimisationParams": {
"avoidPatterns": [
"foo",
"bar"
],
"enforceGc": false,
"hardCodons": [
"foo",
"bar"
],
"maxRepeatLength": 10,
"optimiseForSpecies": "optimiseForSpecies",
"sequence": "sequence",
"sequenceName": "sequenceName"
},
"optimise": false,
"score": false,
"sequence": "sequence",
"toJson": false
}
}
}",
"types": "input FeatureInput {
end: Int!
featureType: String!
name: String!
optimise: Boolean!
start: Int!
}
input OptimisationParamsInput {
avoidPatterns: [String]
enforceGc: Boolean
hardCodons: [String]
maxRepeatLength: Int
optimiseForSpecies: String
sequence: String
sequenceName: String
}
input OptimiserRequestInput {
features: [FeatureInput]!
fromJson: Boolean
geneName: String!
optimisationParams: OptimisationParamsInput!
optimise: Boolean!
score: Boolean
sequence: String!
toJson: Boolean
}
type OptimiserResponse {
geneName: String
postOptimisationPenalties: [Penalty]
postOptimisationScoreDetail: PostOptimisationScoreDetail
postOptimisationSequence: String
preOptimisationPenalties: [Penalty]
preOptimisationScoreDetail: PreOptimisationScoreDetail
preOptimisationSequence: String
}
type Penalty {
end: Int!
group: String!
score: Float!
start: Int!
strand: String!
}
type PostOptimisationScoreDetail {
description: String!
level: String!
score: Float!
}
type PreOptimisationScoreDetail {
description: String!
level: String!
score: Float!
}
",
}
`;

View File

@ -0,0 +1,345 @@
{
"openapi": "3.0.2",
"info": {
"title": "Optimisier API",
"description": "Optimiser",
"contact": { "name": "Team", "email": "test@test.com" },
"version": "0.1.4"
},
"paths": {
"/optimise": {
"post": {
"tags": ["optimise"],
"summary": "Optimise",
"operationId": "optimise_optimise_post",
"requestBody": {
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/OptimiserRequest" }
}
},
"required": true
},
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/OptimiserResponse" }
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/HTTPError" }
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/HTTPError" }
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
}
}
},
"500": {
"description": "Internal Server Error",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/HTTPError" }
}
}
},
"503": {
"description": "Service Unavailable",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/HTTPError" }
}
}
}
}
}
},
"/health": {
"get": {
"tags": ["healthcheck"],
"summary": "Health",
"operationId": "health_health_get",
"responses": {
"200": {
"description": "Successful Response",
"content": { "application/json": { "schema": {} } }
}
}
}
}
},
"components": {
"schemas": {
"Feature": {
"title": "Feature",
"required": ["name", "feature_type", "start", "end", "optimise"],
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string",
"description": "The name of the feature"
},
"feature_type": {
"title": "Feature Type",
"type": "string",
"description": "Feature type e.g. CDS"
},
"start": {
"title": "Start",
"type": "integer",
"description": "Nucleotide start position for feature "
},
"end": {
"title": "End",
"type": "integer",
"description": "Nucleotide end position for feature "
},
"optimise": {
"title": "Optimise",
"type": "boolean",
"description": "Mark this region for optimization?"
}
}
},
"HTTPError": {
"title": "HTTPError",
"required": ["detail"],
"type": "object",
"properties": { "detail": { "title": "Detail", "type": "string" } },
"description": "HTTP error schema to be used when an HTTPException is thrown."
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": { "$ref": "#/components/schemas/ValidationError" }
}
}
},
"OptimisationParams": {
"title": "OptimisationParams",
"type": "object",
"properties": {
"sequence_name": { "title": "Sequence Name", "type": "string" },
"sequence": { "title": "Sequence", "type": "string" },
"optimise_for_species": {
"title": "Optimise For Species",
"type": "string",
"description": "Species to codon optimise for"
},
"avoid_patterns": {
"title": "Avoid Patterns",
"type": "array",
"items": { "type": "string" },
"description": "An array of sequences to avoid"
},
"enforce_gc": {
"title": "Enforce Gc",
"type": "boolean",
"default": false
},
"hard_codons": {
"title": "Hard Codons",
"type": "array",
"items": { "type": "string" },
"default": ["CCA", "GCA", "CTA"]
},
"max_repeat_length": {
"title": "Max Repeat Length",
"type": "integer"
}
}
},
"OptimiserRequest": {
"title": "OptimiserRequest",
"required": [
"gene_name",
"sequence",
"optimise",
"features",
"optimisation_params"
],
"type": "object",
"properties": {
"gene_name": {
"title": "Gene Name",
"type": "string",
"description": "The name of the gene"
},
"sequence": {
"title": "Sequence",
"type": "string",
"description": "The DNA sequence for optimisation"
},
"score": {
"title": "Score",
"type": "boolean",
"description": "Score this sequence?",
"default": true
},
"optimise": {
"title": "Optimise",
"type": "boolean",
"description": "Optimise this sequence?"
},
"features": {
"title": "Features",
"type": "array",
"items": { "$ref": "#/components/schemas/Feature" },
"description": "List of gene features objects"
},
"optimisation_params": {
"title": "Optimisation Params",
"allOf": [{ "$ref": "#/components/schemas/OptimisationParams" }],
"description": "An object to hold parameters for optimisation"
},
"from_json": {
"title": "From Json",
"type": "boolean",
"description": "Input from JSON - to be removed in future versions",
"default": true
},
"to_json": {
"title": "To Json",
"type": "boolean",
"description": "Output to JSON - to be removed in future versions",
"default": true
}
}
},
"OptimiserResponse": {
"title": "OptimiserResponse",
"type": "object",
"properties": {
"gene_name": {
"title": "Gene Name",
"type": "string",
"description": "The name of the gene"
},
"pre_optimisation_sequence": {
"title": "Pre Optimisation Sequence",
"type": "string",
"description": "The raw (pre-optimisation) DNA sequence"
},
"post_optimisation_sequence": {
"title": "Post Optimisation Sequence",
"type": "string",
"description": "The modified (optimised) DNA sequence"
},
"pre_optimisation_penalties": {
"title": "Pre Optimisation Penalties",
"type": "array",
"items": { "$ref": "#/components/schemas/Penalty" },
"description": "An array of objects holding negative scoring sequences found in the pre-optimised DNA sequence"
},
"pre_optimisation_score_detail": {
"title": "Pre Optimisation Score Detail",
"allOf": [{ "$ref": "#/components/schemas/ScoringResult" }],
"description": "A sequence score for the pre-optimised sequence"
},
"post_optimisation_penalties": {
"title": "Post Optimisation Penalties",
"type": "array",
"items": { "$ref": "#/components/schemas/Penalty" },
"description": "An array of objects holding negative scoring sequences found in the optimised DNA sequence"
},
"post_optimisation_score_detail": {
"title": "Post Optimisation Score Detail",
"allOf": [{ "$ref": "#/components/schemas/ScoringResult" }],
"description": "A sequence score for the optimised sequence"
}
}
},
"Penalty": {
"title": "Penalty",
"required": ["start", "end", "group", "score", "strand"],
"type": "object",
"properties": {
"start": {
"title": "Start",
"type": "integer",
"description": "The start position for the penalty sequence"
},
"end": {
"title": "End",
"type": "integer",
"description": "The end position for the penalty sequence"
},
"group": {
"title": "Group",
"type": "string",
"description": "The group that the penalty sequence belongs to"
},
"score": {
"title": "Score",
"type": "number",
"description": "The score for this penalty sequence"
},
"strand": {
"title": "Strand",
"type": "string",
"description": "The strand of DNA that this penalty sequence is found on"
}
}
},
"ScoringResult": {
"title": "ScoringResult",
"required": ["score", "level", "description"],
"type": "object",
"properties": {
"score": {
"title": "Score",
"type": "number",
"description": "The score for this sequence"
},
"level": {
"title": "Level",
"type": "string",
"description": "The level of the score"
},
"description": {
"title": "Description",
"type": "string",
"description": "The details of the score"
}
}
},
"ValidationError": {
"title": "ValidationError",
"required": ["loc", "msg", "type"],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": { "anyOf": [{ "type": "string" }, { "type": "integer" }] }
},
"msg": { "title": "Message", "type": "string" },
"type": { "title": "Error Type", "type": "string" }
}
}
}
}
}

View File

@ -1,6 +1,8 @@
import { Oas3 } from '@hasura/open-api-to-graphql';
import { ParameterObject } from '@hasura/open-api-to-graphql';
import petStore from './petstore.json';
import petStore from './fixtures/petstore.json';
// test case from this issue https://github.com/hasura/graphql-engine/issues/9734
import optimizer from './fixtures/optimizer.json';
import { generateAction, generateQueryParams, parseOas } from './utils';
const tags: ParameterObject = {
@ -119,3 +121,13 @@ describe('generateQueryParams', () => {
);
});
});
describe('optimizer API', () => {
it('should generate correctly', async () => {
const action = await generateAction(
optimizer as unknown as Oas3,
'optimise_optimise_post'
);
expect(action).toMatchSnapshot();
});
});

View File

@ -114,7 +114,7 @@ const createTransform = (
'preferredName' in definition &&
typeof definition.preferredName === 'string'
) {
const newPrefix = prefix.split(/\./)[prefix.split(/\./).length - 1];
const newPrefix = prefix.match(/\['(.*?)'\]/)?.[1] || '';
const { transform, needTransform } = createTransform(
definition.subDefinitions,
newPrefix,
@ -151,7 +151,7 @@ const createTransform = (
needTransform: childrenNeedTransform,
} = createTransform(
value.subDefinitions,
`${prefix}?.${keyTo}`,
`${prefix}?['${keyTo}']`,
inverse
);
needTransform = needTransform || childrenNeedTransform;
@ -162,7 +162,7 @@ const createTransform = (
}
return {
...acc,
[keyFrom]: `{{${prefix}?.${keyTo}}}`,
[keyFrom]: `{{${prefix}?['${keyTo}']}}`,
};
}, {});
return {
@ -416,9 +416,13 @@ export const translateAction = (
sdlWithoutComments
.replace(/"""[^]*?"""/g, '')
.replace(/type Query {[^]*?}/g, '')
.replace(/type QueryPlaceholder {[^]*?}/g, '')
.replace(/type Mutation {[^]*?}/g, '')
.replace(/type MutationPlaceholder {[^]*?}/g, '')
.replace(/type Query\s+/, '')
.replace(/type Mutation\s+/, '')
.replace(/type QueryPlaceholder\s+/, '')
.replace(/type MutationPlaceholder\s+/, '')
);
let sampleInput = JSON.parse(