@platformatic/sql-openapi
Advanced tools
Comparing version 0.12.1 to 0.13.0
@@ -100,2 +100,4 @@ 'use strict' | ||
const mapRoutePathNamesReverseRelations = new Map() | ||
let idxRoutePathNamesReverseRelations = 1 | ||
// For every reverse relationship we create: entity/:entity_Id/target_entity | ||
@@ -112,60 +114,80 @@ for (const reverseRelationship of entity.reverseRelationships) { | ||
const operationId = `get${capitalize(targetEntity.pluralName)}For${capitalize(entity.singularName)}` | ||
app.get(`/:${camelcase(primaryKey)}/${targetEntity.pluralName}`, { | ||
schema: { | ||
operationId, | ||
params: getPrimaryKeyParams(entity, ignore), | ||
querystring: { | ||
type: 'object', | ||
properties: { | ||
fields: getFieldsForEntity(targetEntity, ignore) | ||
let routePathName = targetEntity.relations.length > 1 | ||
? camelcase([reverseRelationship.sourceEntity, targetForeignKeyCamelcase]) | ||
: targetEntity.pluralName | ||
if (mapRoutePathNamesReverseRelations.get(routePathName)) { | ||
idxRoutePathNamesReverseRelations++ | ||
routePathName += idxRoutePathNamesReverseRelations | ||
} else { | ||
mapRoutePathNamesReverseRelations.set(routePathName, true) | ||
} | ||
try { | ||
app.get(`/:${camelcase(primaryKey)}/${routePathName}`, { | ||
schema: { | ||
operationId, | ||
params: getPrimaryKeyParams(entity, ignore), | ||
querystring: { | ||
type: 'object', | ||
properties: { | ||
fields: getFieldsForEntity(targetEntity, ignore) | ||
} | ||
}, | ||
response: { | ||
200: { | ||
type: 'array', | ||
items: targetEntitySchema | ||
} | ||
} | ||
}, | ||
response: { | ||
200: { | ||
type: 'array', | ||
items: targetEntitySchema | ||
} | ||
links: { | ||
200: entityLinks | ||
} | ||
}, | ||
links: { | ||
200: entityLinks | ||
} | ||
}, async function (request, reply) { | ||
const ctx = { app: this, reply } | ||
// IF we want to have HTTP/404 in case the entity does not exist | ||
// we need to do 2 queries. One to check if the entity exists. the other to get the related entities | ||
// Improvement: this could be also done with a single query with a join, | ||
}, async function (request, reply) { | ||
const ctx = { app: this, reply } | ||
// IF we want to have HTTP/404 in case the entity does not exist | ||
// we need to do 2 queries. One to check if the entity exists. the other to get the related entities | ||
// Improvement: this could be also done with a single query with a join, | ||
// check that the entity exists | ||
const resEntity = await entity.count({ | ||
ctx, | ||
where: { | ||
[primaryKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
// check that the entity exists | ||
const resEntity = await entity.count({ | ||
ctx, | ||
where: { | ||
[primaryKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
} | ||
} | ||
}) | ||
if (resEntity === 0) { | ||
return reply.callNotFound() | ||
} | ||
}) | ||
if (resEntity === 0) { | ||
return reply.callNotFound() | ||
} | ||
// get the related entities | ||
const res = await targetEntity.find({ | ||
ctx, | ||
where: { | ||
[targetForeignKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
} | ||
}, | ||
fields: request.query.fields | ||
// get the related entities | ||
const res = await targetEntity.find({ | ||
ctx, | ||
where: { | ||
[targetForeignKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
} | ||
}, | ||
fields: request.query.fields | ||
}) | ||
if (res.length === 0) { | ||
// This is a query on a FK, so | ||
return [] | ||
} | ||
return res | ||
}) | ||
if (res.length === 0) { | ||
// This is a query on a FK, so | ||
return [] | ||
} | ||
return res | ||
}) | ||
} catch (error) /* istanbul ignore next */ { | ||
app.log.error(error) | ||
app.log.info({ routePathName, targetEntityName, targetEntitySchema, operationId }) | ||
throw new Error('Unable to create the route for the reverse relationship') | ||
} | ||
} | ||
const mapRoutePathNamesRelations = new Map() | ||
let idxRoutePathNamesRelations = 1 | ||
// For every relationship we create: entity/:entity_Id/target_entity | ||
@@ -179,3 +201,10 @@ for (const relation of entity.relations) { | ||
// (or multiple relationships between the same entities). We might want to specify this in documentation, because can be confusing | ||
const targetRelation = relation.column_name.replace(/_id$/, '') | ||
let targetRelation = relation.column_name.replace(/_id$/, '') | ||
if (mapRoutePathNamesRelations.get(targetRelation)) { | ||
idxRoutePathNamesRelations++ | ||
targetRelation += idxRoutePathNamesRelations | ||
} else { | ||
mapRoutePathNamesRelations.set(targetRelation, true) | ||
} | ||
const targetEntitySchema = { | ||
@@ -188,51 +217,57 @@ $ref: targetEntity.name + '#' | ||
// We need to get the relation name from the PK column: | ||
app.get(`/:${camelcase(primaryKey)}/${targetRelation}`, { | ||
schema: { | ||
operationId, | ||
params: getPrimaryKeyParams(entity, ignore), | ||
querystring: { | ||
type: 'object', | ||
properties: { | ||
fields: getFieldsForEntity(targetEntity, ignore) | ||
try { | ||
app.get(`/:${camelcase(primaryKey)}/${targetRelation}`, { | ||
schema: { | ||
operationId, | ||
params: getPrimaryKeyParams(entity, ignore), | ||
querystring: { | ||
type: 'object', | ||
properties: { | ||
fields: getFieldsForEntity(targetEntity, ignore) | ||
} | ||
}, | ||
response: { | ||
200: targetEntitySchema | ||
} | ||
}, | ||
response: { | ||
200: targetEntitySchema | ||
links: { | ||
200: entityLinks | ||
} | ||
}, | ||
links: { | ||
200: entityLinks | ||
} | ||
}, async function (request, reply) { | ||
const ctx = { app: this, reply } | ||
// check that the entity exists | ||
const resEntity = (await entity.find({ | ||
ctx, | ||
where: { | ||
[primaryKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
}, async function (request, reply) { | ||
const ctx = { app: this, reply } | ||
// check that the entity exists | ||
const resEntity = (await entity.find({ | ||
ctx, | ||
where: { | ||
[primaryKeyCamelcase]: { | ||
eq: request.params[primaryKeyCamelcase] | ||
} | ||
} | ||
}))[0] | ||
if (!resEntity) { | ||
return reply.callNotFound() | ||
} | ||
}))[0] | ||
if (!resEntity) { | ||
return reply.callNotFound() | ||
} | ||
// get the related entity | ||
const res = await targetEntity.find({ | ||
ctx, | ||
where: { | ||
[targetForeignKeyCamelcase]: { | ||
eq: resEntity[targetColumnCamelcase] | ||
} | ||
}, | ||
fields: request.query.fields | ||
}) | ||
// get the related entity | ||
const res = await targetEntity.find({ | ||
ctx, | ||
where: { | ||
[targetForeignKeyCamelcase]: { | ||
eq: resEntity[targetColumnCamelcase] | ||
} | ||
}, | ||
fields: request.query.fields | ||
if (res.length === 0) { | ||
return reply.callNotFound() | ||
} | ||
return res[0] | ||
}) | ||
if (res.length === 0) { | ||
return reply.callNotFound() | ||
} | ||
return res[0] | ||
}) | ||
} catch (error) /* istanbul ignore next */ { | ||
app.log.error(error) | ||
app.log.info({ primaryKey, targetRelation, targetEntitySchema, targetEntityName, targetEntity, operationId }) | ||
throw new Error('Unable to create the route for the PK col relationship') | ||
} | ||
} | ||
@@ -239,0 +274,0 @@ |
{ | ||
"name": "@platformatic/sql-openapi", | ||
"version": "0.12.1", | ||
"version": "0.13.0", | ||
"description": "Map a SQL database to OpenAPI, for Fastify", | ||
@@ -24,3 +24,3 @@ "main": "index.js", | ||
"tsd": "^0.25.0", | ||
"@platformatic/sql-mapper": "0.12.1" | ||
"@platformatic/sql-mapper": "0.13.0" | ||
}, | ||
@@ -34,3 +34,3 @@ "dependencies": { | ||
"inflected": "^2.1.0", | ||
"@platformatic/sql-json-schema-mapper": "0.12.1" | ||
"@platformatic/sql-json-schema-mapper": "0.13.0" | ||
}, | ||
@@ -37,0 +37,0 @@ "tsd": { |
409803
34
15011
+ Added@platformatic/sql-json-schema-mapper@0.13.0(transitive)
- Removed@platformatic/sql-json-schema-mapper@0.12.1(transitive)