Skip to content

Commit f60e61a

Browse files
danielsharveytheoomoregbee
authored andcommitted
fix: Re-add missing query parameters for shortcut blueprint create
Two recent changes (aeda736 and f49fab3) conflicted. This fix corrects shortcut create blueprints which generate query parameters from the model schema but did not account for the change to `required` handling (which ensured required was not enforced for update blueprints).
1 parent f49fab3 commit f60e61a

File tree

3 files changed

+173
-5
lines changed

3 files changed

+173
-5
lines changed

lib/generators.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import forEach from 'lodash/forEach';
1212
import { OpenApi } from '../types/openapi';
1313
import set from 'lodash/set';
1414
import { map, omit, isEqual, reduce } from 'lodash';
15-
import { attributeValidations, resolveRef } from './utils';
15+
import { attributeValidations, resolveRef, unrollSchema } from './utils';
1616

1717

1818
/**
@@ -478,7 +478,7 @@ export const generatePaths = (routes: SwaggerRouteInfo[], templates: BlueprintAc
478478
if(route.actionType === 'shortcutBlueprint') {
479479
const schema = specification!.components!.schemas?.[route.model!.identity];
480480
if (schema) {
481-
const resolvedSchema = resolveRef(specification, schema);
481+
const resolvedSchema = unrollSchema(specification, schema);
482482
if (resolvedSchema) {
483483
generateSchemaAsQueryParameters(resolvedSchema as OpenApi.UpdatedSchema).map(p => {
484484
if (isParam('query', p.name)) return;

lib/utils/index.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { BluePrintAction } from '../interfaces';
22
import swaggerJSDoc from 'swagger-jsdoc';
33
import { OpenApi } from '../../types/openapi';
4-
import { get } from 'lodash';
4+
import { get, cloneDeep, defaultsDeep } from 'lodash';
55
import { Reference } from 'swagger-schema-official';
66

77
export const blueprintActions: Array<BluePrintAction> = ['findone', 'find', 'create', 'update', 'destroy', 'populate', 'add', 'remove', 'replace'];
@@ -73,3 +73,34 @@ export const resolveRef = (specification: OpenApi.OpenApi, obj: (Reference | unk
7373
return obj;
7474

7575
}
76+
77+
/**
78+
* Provides limited dereferencing, or unrolling, of schemas.
79+
*
80+
* Background: The generator `generateSchemas()` produces two variants:
81+
* 1. The `without-required-constraint` variant containing the properties but without
82+
* the specifying required fields (used for update blueprint).
83+
* 2. A primary variant containing an `allOf` union of the variant above
84+
* and the `required` constraint (used for the create blueprint).
85+
*
86+
* This method handles this simple case, resolving references and unrolling
87+
* into a simple cloned schema with directly contained properties.
88+
*
89+
* Otherwise, schema returned as clone but unmodified.
90+
*
91+
* @param specification
92+
* @param schema
93+
*/
94+
export const unrollSchema = (specification: OpenApi.OpenApi, schema: OpenApi.UpdatedSchema | Reference): OpenApi.UpdatedSchema => {
95+
96+
const ret: OpenApi.UpdatedSchema = cloneDeep(resolveRef(specification, schema) as OpenApi.UpdatedSchema);
97+
98+
if(ret.allOf) {
99+
const allOf = ret.allOf;
100+
delete ret.allOf;
101+
allOf.map(s => defaultsDeep(ret, resolveRef(specification, s)));
102+
}
103+
104+
return ret;
105+
106+
}

test/fixtures/generatedSwagger.json

+139-2
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,55 @@
10001000
"tags": [
10011001
"Pet"
10021002
],
1003-
"parameters": [],
1003+
"parameters": [
1004+
{
1005+
"in": "query",
1006+
"name": "petID",
1007+
"schema": {
1008+
"type": "integer",
1009+
"format": "int64",
1010+
"uniqueItems": true,
1011+
"description": "Note Sails special attributes: autoIncrement",
1012+
"readOnly": true
1013+
},
1014+
"description": "Note Sails special attributes: autoIncrement"
1015+
},
1016+
{
1017+
"in": "query",
1018+
"name": "names",
1019+
"schema": {
1020+
"type": "string",
1021+
"example": "Pet's full name"
1022+
},
1023+
"required": true
1024+
},
1025+
{
1026+
"in": "query",
1027+
"name": "owner",
1028+
"schema": {
1029+
"description": "JSON dictionary representing the **user** instance or FK when creating / updating / not populated",
1030+
"oneOf": [
1031+
{
1032+
"$ref": "#/components/schemas/user"
1033+
}
1034+
]
1035+
},
1036+
"description": "JSON dictionary representing the **user** instance or FK when creating / updating / not populated"
1037+
},
1038+
{
1039+
"in": "query",
1040+
"name": "caredForBy",
1041+
"schema": {
1042+
"description": "JSON dictionary representing the **user** instance or FK when creating / updating / not populated",
1043+
"oneOf": [
1044+
{
1045+
"$ref": "#/components/schemas/user"
1046+
}
1047+
]
1048+
},
1049+
"description": "JSON dictionary representing the **user** instance or FK when creating / updating / not populated"
1050+
}
1051+
],
10041052
"responses": {
10051053
"200": {
10061054
"description": "Responds with a JSON dictionary representing the newly created **Pet** instance",
@@ -1300,7 +1348,96 @@
13001348
"User (ORM duplicate)",
13011349
"User (ORM)"
13021350
],
1303-
"parameters": [],
1351+
"parameters": [
1352+
{
1353+
"in": "query",
1354+
"name": "id",
1355+
"schema": {
1356+
"type": "integer",
1357+
"format": "int64",
1358+
"uniqueItems": true,
1359+
"description": "Note Sails special attributes: autoIncrement"
1360+
},
1361+
"description": "Note Sails special attributes: autoIncrement"
1362+
},
1363+
{
1364+
"in": "query",
1365+
"name": "names",
1366+
"schema": {
1367+
"type": "string",
1368+
"example": "First Middle Last"
1369+
},
1370+
"required": true
1371+
},
1372+
{
1373+
"in": "query",
1374+
"name": "email",
1375+
"schema": {
1376+
"type": "string",
1377+
"format": "email",
1378+
"description": "Just any old email"
1379+
},
1380+
"description": "Just any old email"
1381+
},
1382+
{
1383+
"in": "query",
1384+
"name": "sex",
1385+
"schema": {
1386+
"type": "string",
1387+
"enum": [
1388+
"Male",
1389+
"Female"
1390+
]
1391+
}
1392+
},
1393+
{
1394+
"in": "query",
1395+
"name": "ageLimit",
1396+
"schema": {
1397+
"type": "number",
1398+
"format": "double",
1399+
"maximum": 100,
1400+
"minimum": 15
1401+
}
1402+
},
1403+
{
1404+
"in": "query",
1405+
"name": "pets",
1406+
"schema": {
1407+
"description": "Array of **pet**'s or array of FK's when creating / updating / not populated",
1408+
"type": "array",
1409+
"items": {
1410+
"$ref": "#/components/schemas/pet"
1411+
}
1412+
},
1413+
"description": "Array of **pet**'s or array of FK's when creating / updating / not populated"
1414+
},
1415+
{
1416+
"in": "query",
1417+
"name": "favouritePet",
1418+
"schema": {
1419+
"description": "JSON dictionary representing the **pet** instance or FK when creating / updating / not populated",
1420+
"oneOf": [
1421+
{
1422+
"$ref": "#/components/schemas/pet"
1423+
}
1424+
]
1425+
},
1426+
"description": "JSON dictionary representing the **pet** instance or FK when creating / updating / not populated"
1427+
},
1428+
{
1429+
"in": "query",
1430+
"name": "neighboursPets",
1431+
"schema": {
1432+
"description": "Array of **pet**'s or array of FK's when creating / updating / not populated",
1433+
"type": "array",
1434+
"items": {
1435+
"$ref": "#/components/schemas/pet"
1436+
}
1437+
},
1438+
"description": "Array of **pet**'s or array of FK's when creating / updating / not populated"
1439+
}
1440+
],
13041441
"responses": {
13051442
"200": {
13061443
"description": "Responds with a JSON dictionary representing the newly created **User** instance",

0 commit comments

Comments
 (0)