@platformatic/sql-openapi 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/eslint.config.js +2 -2
- package/index.d.ts +3 -0
- package/index.js +33 -34
- package/lib/cursor.js +94 -0
- package/lib/entity-to-routes.js +252 -202
- package/lib/errors.js +25 -8
- package/lib/many-to-many.js +99 -81
- package/lib/shared.js +220 -135
- package/lib/utils.js +2 -8
- package/package.json +21 -18
package/lib/many-to-many.js
CHANGED
|
@@ -1,36 +1,44 @@
|
|
|
1
|
-
|
|
1
|
+
import { mapSQLTypeToOpenAPIType } from '@platformatic/sql-json-schema-mapper'
|
|
2
|
+
import camelcase from 'camelcase'
|
|
3
|
+
import { capitalize, generateArgs, getFieldsForEntity, rootEntityRoutes } from './shared.js'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const camelcase = require('camelcase')
|
|
5
|
-
const { generateArgs, capitalize, getFieldsForEntity, rootEntityRoutes } = require('./shared')
|
|
6
|
-
|
|
7
|
-
async function entityPlugin (app, opts) {
|
|
5
|
+
export async function manyToMany (app, opts) {
|
|
8
6
|
const entity = opts.entity
|
|
9
7
|
const ignore = opts.ignore
|
|
10
8
|
const ignoreRoutes = opts.ignoreRoutes
|
|
11
9
|
|
|
12
10
|
const entitySchema = {
|
|
13
|
-
$ref: entity.name + '#'
|
|
11
|
+
$ref: entity.name + '#'
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
const entitySchemaInput = {
|
|
17
|
-
$ref: entity.name + 'Input#'
|
|
15
|
+
$ref: entity.name + 'Input#'
|
|
18
16
|
}
|
|
19
17
|
const primaryKeysParams = getPrimaryKeysParams(entity)
|
|
20
|
-
const primaryKeysCamelcase = Array.from(entity.primaryKeys).map(
|
|
18
|
+
const primaryKeysCamelcase = Array.from(entity.primaryKeys).map(key => camelcase(key))
|
|
21
19
|
|
|
22
20
|
const { whereArgs, orderByArgs } = generateArgs(entity, ignore)
|
|
23
21
|
|
|
24
22
|
const fields = getFieldsForEntity(entity, ignore)
|
|
25
23
|
|
|
26
|
-
rootEntityRoutes(
|
|
24
|
+
rootEntityRoutes(
|
|
25
|
+
app,
|
|
26
|
+
entity,
|
|
27
|
+
whereArgs,
|
|
28
|
+
orderByArgs,
|
|
29
|
+
undefined,
|
|
30
|
+
entitySchema,
|
|
31
|
+
fields,
|
|
32
|
+
entitySchemaInput,
|
|
33
|
+
ignoreRoutes
|
|
34
|
+
)
|
|
27
35
|
|
|
28
36
|
let pathWithParams = ''
|
|
29
37
|
let openapiPathWithParams = ''
|
|
30
38
|
|
|
31
39
|
for (const key of entity.primaryKeys) {
|
|
32
40
|
const camelcaseKey = camelcase(key)
|
|
33
|
-
const relation = entity.relations.find(
|
|
41
|
+
const relation = entity.relations.find(relation => relation.column_name === key)
|
|
34
42
|
if (relation) {
|
|
35
43
|
pathWithParams += `/${relation.foreignEntityName}/:${camelcaseKey}`
|
|
36
44
|
openapiPathWithParams += `${app.prefix}/${relation.foreignEntityName}/{${camelcaseKey}}`
|
|
@@ -52,38 +60,42 @@ async function entityPlugin (app, opts) {
|
|
|
52
60
|
})
|
|
53
61
|
|
|
54
62
|
if (!ignoredGetWithParams) {
|
|
55
|
-
app.get(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
app.get(
|
|
64
|
+
pathWithParams,
|
|
65
|
+
{
|
|
66
|
+
schema: {
|
|
67
|
+
operationId: `get${entity.name}By${operationName}`,
|
|
68
|
+
summary: `Get ${entity.name} by ${operationName}.`,
|
|
69
|
+
description: `Fetch ${entity.name} by ${operationName} from the database.`,
|
|
70
|
+
params: primaryKeysParams,
|
|
71
|
+
tags: [entity.table],
|
|
72
|
+
querystring: {
|
|
73
|
+
type: 'object',
|
|
74
|
+
properties: {
|
|
75
|
+
fields
|
|
76
|
+
}
|
|
66
77
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
78
|
+
response: {
|
|
79
|
+
200: entitySchema
|
|
80
|
+
}
|
|
81
|
+
}
|
|
71
82
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
async function (request, reply) {
|
|
84
|
+
const ctx = { app: this, reply }
|
|
85
|
+
const res = await entity.find({
|
|
86
|
+
ctx,
|
|
87
|
+
where: primaryKeysCamelcase.reduce((acc, key) => {
|
|
88
|
+
acc[key] = { eq: request.params[key] }
|
|
89
|
+
return acc
|
|
90
|
+
}, {}),
|
|
91
|
+
fields: request.query.fields
|
|
92
|
+
})
|
|
93
|
+
if (res.length === 0) {
|
|
94
|
+
return reply.callNotFound()
|
|
95
|
+
}
|
|
96
|
+
return res[0]
|
|
84
97
|
}
|
|
85
|
-
|
|
86
|
-
})
|
|
98
|
+
)
|
|
87
99
|
}
|
|
88
100
|
|
|
89
101
|
for (const method of ['POST', 'PUT']) {
|
|
@@ -104,30 +116,32 @@ async function entityPlugin (app, opts) {
|
|
|
104
116
|
querystring: {
|
|
105
117
|
type: 'object',
|
|
106
118
|
properties: {
|
|
107
|
-
fields
|
|
108
|
-
}
|
|
119
|
+
fields
|
|
120
|
+
}
|
|
109
121
|
},
|
|
110
122
|
response: {
|
|
111
|
-
200: entitySchema
|
|
112
|
-
}
|
|
123
|
+
200: entitySchema
|
|
124
|
+
}
|
|
113
125
|
},
|
|
114
126
|
async handler (request, reply) {
|
|
115
|
-
const ids = primaryKeysCamelcase.map(
|
|
127
|
+
const ids = primaryKeysCamelcase.map(key => {
|
|
128
|
+
return { key, value: request.params[key] }
|
|
129
|
+
})
|
|
116
130
|
const ctx = { app: this, reply }
|
|
117
131
|
const res = await entity.save({
|
|
118
132
|
ctx,
|
|
119
133
|
input: {
|
|
120
134
|
...request.body,
|
|
121
|
-
...
|
|
135
|
+
...ids.reduce((acc, { key, value }) => {
|
|
122
136
|
acc[key] = value
|
|
123
137
|
return acc
|
|
124
|
-
}, {})
|
|
138
|
+
}, {})
|
|
125
139
|
},
|
|
126
140
|
where: ids.reduce((acc, { key, value }) => {
|
|
127
141
|
acc[key] = { eq: value }
|
|
128
142
|
return acc
|
|
129
143
|
}, {}),
|
|
130
|
-
fields: request.query.fields
|
|
144
|
+
fields: request.query.fields
|
|
131
145
|
})
|
|
132
146
|
let location = app.prefix + pathWithParams
|
|
133
147
|
for (const key of primaryKeysCamelcase) {
|
|
@@ -135,7 +149,7 @@ async function entityPlugin (app, opts) {
|
|
|
135
149
|
}
|
|
136
150
|
reply.header('location', location)
|
|
137
151
|
return res
|
|
138
|
-
}
|
|
152
|
+
}
|
|
139
153
|
})
|
|
140
154
|
}
|
|
141
155
|
}
|
|
@@ -145,38 +159,44 @@ async function entityPlugin (app, opts) {
|
|
|
145
159
|
})
|
|
146
160
|
|
|
147
161
|
if (!ignoredDeleteWithParams) {
|
|
148
|
-
app.delete(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
app.delete(
|
|
163
|
+
pathWithParams,
|
|
164
|
+
{
|
|
165
|
+
schema: {
|
|
166
|
+
summary: `Delete ${entity.name} by ${operationName}.`,
|
|
167
|
+
description: `Delete ${entity.name} by ${operationName} from the database.`,
|
|
168
|
+
params: primaryKeysParams,
|
|
169
|
+
tags: [entity.table],
|
|
170
|
+
querystring: {
|
|
171
|
+
type: 'object',
|
|
172
|
+
properties: {
|
|
173
|
+
fields
|
|
174
|
+
}
|
|
158
175
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
176
|
+
response: {
|
|
177
|
+
200: entitySchema
|
|
178
|
+
}
|
|
179
|
+
}
|
|
163
180
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
ctx,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
181
|
+
async function (request, reply) {
|
|
182
|
+
const ids = primaryKeysCamelcase.map(key => {
|
|
183
|
+
return { key, value: request.params[key] }
|
|
184
|
+
})
|
|
185
|
+
const ctx = { app: this, reply }
|
|
186
|
+
const res = await entity.delete({
|
|
187
|
+
ctx,
|
|
188
|
+
where: ids.reduce((acc, { key, value }) => {
|
|
189
|
+
acc[key] = { eq: value }
|
|
190
|
+
return acc
|
|
191
|
+
}, {}),
|
|
192
|
+
fields: request.query.fields
|
|
193
|
+
})
|
|
194
|
+
if (res.length === 0) {
|
|
195
|
+
return reply.callNotFound()
|
|
196
|
+
}
|
|
197
|
+
return res[0]
|
|
177
198
|
}
|
|
178
|
-
|
|
179
|
-
})
|
|
199
|
+
)
|
|
180
200
|
}
|
|
181
201
|
}
|
|
182
202
|
|
|
@@ -194,8 +214,6 @@ function getPrimaryKeysParams (entity) {
|
|
|
194
214
|
return {
|
|
195
215
|
type: 'object',
|
|
196
216
|
properties,
|
|
197
|
-
required
|
|
217
|
+
required
|
|
198
218
|
}
|
|
199
219
|
}
|
|
200
|
-
|
|
201
|
-
module.exports = entityPlugin
|