mirror of https://github.com/nocodb/nocodb
Browse Source
* feat: allow user to include/exclude nested fields and by default only extract pk&pv Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: api metrics Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: add missing await and code cleanup Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: corrections in ast population Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: map default primary value column on table create and include field param for belongsTo column Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: old data list api response correction and count api Signed-off-by: Pranav C <pranavxc@gmail.com>pull/1901/head
Pranav C
3 years ago
committed by
GitHub
20 changed files with 25456 additions and 267 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,99 @@ |
|||||||
|
import View from '../../../../noco-models/View'; |
||||||
|
import { isSystemColumn, UITypes } from 'nocodb-sdk'; |
||||||
|
import Model from '../../../../noco-models/Model'; |
||||||
|
import LinkToAnotherRecordColumn from '../../../../noco-models/LinkToAnotherRecordColumn'; |
||||||
|
|
||||||
|
const getAst = async ({ |
||||||
|
query, |
||||||
|
extractOnlyPrimaries = false, |
||||||
|
includePkByDefault = true, |
||||||
|
model, |
||||||
|
view |
||||||
|
}: { |
||||||
|
query?: RequestQuery; |
||||||
|
extractOnlyPrimaries?: boolean; |
||||||
|
includePkByDefault?: boolean; |
||||||
|
model: Model; |
||||||
|
view?: View; |
||||||
|
}) => { |
||||||
|
if (!model.columns?.length) await model.getColumns(); |
||||||
|
if (extractOnlyPrimaries) { |
||||||
|
return { |
||||||
|
[model.primaryKey.title]: 1, |
||||||
|
[model.primaryValue.title]: 1 |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
let fields = query?.fields || query?.f; |
||||||
|
if (fields && fields !== '*') { |
||||||
|
fields = Array.isArray(fields) ? fields : fields.split(','); |
||||||
|
} else { |
||||||
|
fields = null; |
||||||
|
} |
||||||
|
|
||||||
|
let allowedCols = null; |
||||||
|
if (view) |
||||||
|
allowedCols = (await View.getColumns(view.id)).reduce( |
||||||
|
(o, c) => ({ |
||||||
|
...o, |
||||||
|
[c.fk_column_id]: c.show |
||||||
|
}), |
||||||
|
{} |
||||||
|
); |
||||||
|
|
||||||
|
return model.columns.reduce(async (obj, col) => { |
||||||
|
let value: number | boolean | { [key: string]: any } = 1; |
||||||
|
const nestedFields = |
||||||
|
query?.nested?.[col.title]?.fields || query?.nested?.[col.title]?.f; |
||||||
|
if (nestedFields && nestedFields !== '*') { |
||||||
|
if (col.uidt === UITypes.LinkToAnotherRecord) { |
||||||
|
const model = await col |
||||||
|
.getColOptions<LinkToAnotherRecordColumn>() |
||||||
|
.then(colOpt => colOpt.getRelatedTable()); |
||||||
|
|
||||||
|
value = await getAst({ |
||||||
|
model, |
||||||
|
query: query?.nested?.[col.title] |
||||||
|
}); |
||||||
|
} else { |
||||||
|
value = (Array.isArray(fields) ? fields : fields.split(',')).reduce( |
||||||
|
(o, f) => ({ ...o, [f]: 1 }), |
||||||
|
{} |
||||||
|
); |
||||||
|
} |
||||||
|
} else if (col.uidt === UITypes.LinkToAnotherRecord) { |
||||||
|
const model = await col |
||||||
|
.getColOptions<LinkToAnotherRecordColumn>() |
||||||
|
.then(colOpt => colOpt.getRelatedTable()); |
||||||
|
|
||||||
|
value = await getAst({ |
||||||
|
model, |
||||||
|
query: query?.nested, |
||||||
|
extractOnlyPrimaries: true |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
...(await obj), |
||||||
|
[col.title]: |
||||||
|
allowedCols && (!includePkByDefault || !col.pk) |
||||||
|
? allowedCols[col.id] && |
||||||
|
(!isSystemColumn(col) || view.show_system_fields) && |
||||||
|
(!fields?.length || fields.includes(col.title)) && |
||||||
|
value |
||||||
|
: fields?.length |
||||||
|
? fields.includes(col.title) |
||||||
|
: value |
||||||
|
}; |
||||||
|
}, Promise.resolve({})); |
||||||
|
}; |
||||||
|
|
||||||
|
type RequestQuery = { |
||||||
|
[fields in 'f' | 'fields']?: string | string[]; |
||||||
|
} & { |
||||||
|
nested?: { |
||||||
|
[field: string]: RequestQuery; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
export default getAst; |
@ -0,0 +1,19 @@ |
|||||||
|
import { Request } from 'express'; |
||||||
|
import { Tele } from 'nc-help'; |
||||||
|
|
||||||
|
const countMap = {}; |
||||||
|
|
||||||
|
const metrics = async (req: Request) => { |
||||||
|
if (!req?.route?.path) return; |
||||||
|
const event = `a:api:${req.route.path}:${req.method}`; |
||||||
|
countMap[event] = (countMap[event] || 0) + 1; |
||||||
|
if (countMap[event] >= 50) { |
||||||
|
Tele.event({ event }); |
||||||
|
countMap[event] = 0; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default async (req: Request, _res, next) => { |
||||||
|
metrics(req).then(() => {}); |
||||||
|
next(); |
||||||
|
}; |
Loading…
Reference in new issue