prisma-generator-express 1.50.0 → 1.51.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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-generator-express",
|
|
3
3
|
"description": "Prisma generator for Express, Fastify, and Hono CRUD APIs with OpenAPI documentation",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.51.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
@@ -21,6 +21,7 @@ type ViewDef = {
|
|
|
21
21
|
defaultLimit?: number
|
|
22
22
|
maxLimit?: number
|
|
23
23
|
orderBy?: OrderByDef
|
|
24
|
+
allowedOrderBy?: string[]
|
|
24
25
|
authorize?: (
|
|
25
26
|
req: Request,
|
|
26
27
|
viewName: string,
|
|
@@ -102,6 +103,47 @@ const buildOrderBy = (orderBy?: OrderByDef): string => {
|
|
|
102
103
|
)
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
const parseOrderByParam = (raw: unknown): OrderByDef | undefined => {
|
|
107
|
+
if (raw === undefined || raw === null || raw === '') return undefined
|
|
108
|
+
if (typeof raw !== 'string') return undefined
|
|
109
|
+
if (raw.startsWith('{') || raw.startsWith('[')) {
|
|
110
|
+
let parsed: unknown
|
|
111
|
+
try {
|
|
112
|
+
parsed = JSON.parse(raw)
|
|
113
|
+
} catch {
|
|
114
|
+
throw new HttpError(400, 'invalid orderBy JSON')
|
|
115
|
+
}
|
|
116
|
+
if (typeof parsed === 'string') return parsed
|
|
117
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
118
|
+
const keys = Object.keys(parsed as Record<string, unknown>)
|
|
119
|
+
if (keys.length === 0) return undefined
|
|
120
|
+
const field = keys[0]
|
|
121
|
+
const dirRaw = (parsed as Record<string, unknown>)[field]
|
|
122
|
+
if (dirRaw === 'asc' || dirRaw === 'desc')
|
|
123
|
+
return { field, direction: dirRaw }
|
|
124
|
+
if (dirRaw && typeof dirRaw === 'object') {
|
|
125
|
+
const sort = (dirRaw as { sort?: unknown }).sort
|
|
126
|
+
const nulls = (dirRaw as { nulls?: unknown }).nulls
|
|
127
|
+
const direction = sort === 'asc' || sort === 'desc' ? sort : undefined
|
|
128
|
+
const nullsOrder =
|
|
129
|
+
nulls === 'first' || nulls === 'last' ? nulls : undefined
|
|
130
|
+
return { field, direction, nulls: nullsOrder }
|
|
131
|
+
}
|
|
132
|
+
return { field }
|
|
133
|
+
}
|
|
134
|
+
throw new HttpError(400, 'invalid orderBy shape')
|
|
135
|
+
}
|
|
136
|
+
return raw
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const enforceAllowlist = (orderBy: OrderByDef, allowed?: string[]): void => {
|
|
140
|
+
if (!allowed) return
|
|
141
|
+
const field = typeof orderBy === 'string' ? orderBy : orderBy.field
|
|
142
|
+
if (!allowed.includes(field)) {
|
|
143
|
+
throw new HttpError(400, 'orderBy field not allowed: ' + field)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
105
147
|
export const materializedViewsRouter = (
|
|
106
148
|
opts: MaterializedRouterOptions,
|
|
107
149
|
): Router => {
|
|
@@ -130,7 +172,11 @@ export const materializedViewsRouter = (
|
|
|
130
172
|
)
|
|
131
173
|
const skip = clampInt(req.query.skip, 0, 0, Number.MAX_SAFE_INTEGER)
|
|
132
174
|
|
|
133
|
-
|
|
175
|
+
const queryOrderBy = parseOrderByParam(req.query.orderBy)
|
|
176
|
+
if (queryOrderBy) enforceAllowlist(queryOrderBy, def.allowedOrderBy)
|
|
177
|
+
const effectiveOrderBy = queryOrderBy ?? def.orderBy
|
|
178
|
+
|
|
179
|
+
if (skip > 0 && !effectiveOrderBy) {
|
|
134
180
|
throw new HttpError(
|
|
135
181
|
400,
|
|
136
182
|
'skip requires orderBy for deterministic pagination',
|
|
@@ -140,7 +186,7 @@ export const materializedViewsRouter = (
|
|
|
140
186
|
const sql =
|
|
141
187
|
'SELECT * FROM ' +
|
|
142
188
|
buildFqn(def) +
|
|
143
|
-
buildOrderBy(
|
|
189
|
+
buildOrderBy(effectiveOrderBy) +
|
|
144
190
|
' LIMIT $1 OFFSET $2'
|
|
145
191
|
|
|
146
192
|
const rows = await opts.prisma.$queryRawUnsafe<unknown[]>(
|