From a49704f373f0099e2b04e82cc97d28c9427233b6 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 1 Mar 2023 18:37:03 +0530 Subject: [PATCH] refactor: relation data apis and deprecated api Signed-off-by: Pranav C --- .../lib/controllers/dataController/index.ts | 19 +- .../dataController/nestedAndDeprecated.ts | 192 +++++++ .../src/lib/services/dataService/index.ts | 475 +++++++++++++++++- 3 files changed, 677 insertions(+), 9 deletions(-) create mode 100644 packages/nocodb/src/lib/controllers/dataController/nestedAndDeprecated.ts diff --git a/packages/nocodb/src/lib/controllers/dataController/index.ts b/packages/nocodb/src/lib/controllers/dataController/index.ts index 52973d639c..d2c11c8a92 100644 --- a/packages/nocodb/src/lib/controllers/dataController/index.ts +++ b/packages/nocodb/src/lib/controllers/dataController/index.ts @@ -98,16 +98,19 @@ async function dataRead(req: Request, res: Response) { rowId: req.params.rowId, query: req.query, }) + ); } async function dataExist(req: Request, res: Response) { - res.json(await dataService.dataExist({ - projectName: req.params.projectName, - tableName: req.params.tableName, - viewName: req.params.viewName, - rowId: req.params.rowId, - query: req.query, - })); + res.json( + await dataService.dataExist({ + projectName: req.params.projectName, + tableName: req.params.tableName, + viewName: req.params.viewName, + rowId: req.params.rowId, + query: req.query, + }) + ); } // todo: Handle the error case where view doesnt belong to model @@ -118,7 +121,7 @@ async function groupedDataList(req: Request, res: Response) { tableName: req.params.tableName, viewName: req.params.viewName, query: req.query, - columnId: req.params.columnId + columnId: req.params.columnId, }); const elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime)); res.setHeader('xc-db-response', elapsedSeconds); diff --git a/packages/nocodb/src/lib/controllers/dataController/nestedAndDeprecated.ts b/packages/nocodb/src/lib/controllers/dataController/nestedAndDeprecated.ts new file mode 100644 index 0000000000..6914383321 --- /dev/null +++ b/packages/nocodb/src/lib/controllers/dataController/nestedAndDeprecated.ts @@ -0,0 +1,192 @@ +import { Request, Response, Router } from 'express'; +import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw'; +import apiMetrics from '../../meta/helpers/apiMetrics'; +import { dataService } from '../../services'; + +export async function dataList(req: Request, res: Response) { + res.json( + await dataService.dataListByViewId({ + viewId: req.params.viewId, + query: req.query, + }) + ); +} + +export async function mmList(req: Request, res: Response) { + res.json( + await dataService.mmList({ + viewId: req.params.viewId, + colId: req.params.colId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +export async function mmExcludedList(req: Request, res: Response) { + res.json( + await dataService.mmExcludedList({ + viewId: req.params.viewId, + colId: req.params.colId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +export async function hmExcludedList(req: Request, res: Response) { + res.json( + await dataService.hmExcludedList({ + viewId: req.params.viewId, + colId: req.params.colId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +export async function btExcludedList(req: Request, res: Response) { + res.json( + await dataService.btExcludedList({ + viewId: req.params.viewId, + colId: req.params.colId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +export async function hmList(req: Request, res: Response) { + res.json( + await dataService.hmList({ + viewId: req.params.viewId, + colId: req.params.colId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +async function dataRead(req: Request, res: Response) { + res.json( + await dataService.dataReadByViewId({ + viewId: req.params.viewId, + rowId: req.params.rowId, + query: req.query, + }) + ); +} + +async function dataInsert(req: Request, res: Response) { + res.json( + await dataService.dataInsertByViewId({ + viewId: req.params.viewId, + body: req.body, + cookie: req, + }) + ); +} + +async function dataUpdate(req: Request, res: Response) { + res.json( + await dataService.dataUpdateByViewId({ + viewId: req.params.viewId, + rowId: req.params.rowId, + body: req.body, + cookie: req, + }) + ); +} + +async function dataDelete(req: Request, res: Response) { + res.json( + await dataService.dataDeleteByViewId({ + viewId: req.params.viewId, + rowId: req.params.rowId, + cookie: req, + }) + ); +} + +async function relationDataDelete(req, res) { + await dataService.relationDataDelete({ + viewId: req.params.viewId, + colId: req.params.colId, + childId: req.params.childId, + rowId: req.params.rowId, + cookie: req, + }); + + res.json({ msg: 'success' }); +} + +//@ts-ignore +async function relationDataAdd(req, res) { + await dataService.relationDataAdd({ + viewId: req.params.viewId, + colId: req.params.colId, + childId: req.params.childId, + rowId: req.params.rowId, + cookie: req, + }); + + res.json({ msg: 'success' }); +} + +const router = Router({ mergeParams: true }); + +router.get('/data/:viewId/', apiMetrics, ncMetaAclMw(dataList, 'dataList')); +router.post( + '/data/:viewId/', + apiMetrics, + ncMetaAclMw(dataInsert, 'dataInsert') +); +router.get( + '/data/:viewId/:rowId', + apiMetrics, + ncMetaAclMw(dataRead, 'dataRead') +); +router.patch( + '/data/:viewId/:rowId', + apiMetrics, + ncMetaAclMw(dataUpdate, 'dataUpdate') +); +router.delete( + '/data/:viewId/:rowId', + apiMetrics, + ncMetaAclMw(dataDelete, 'dataDelete') +); + +router.get( + '/data/:viewId/:rowId/mm/:colId', + apiMetrics, + ncMetaAclMw(mmList, 'mmList') +); +router.get( + '/data/:viewId/:rowId/hm/:colId', + apiMetrics, + ncMetaAclMw(hmList, 'hmList') +); + +router.get( + '/data/:viewId/:rowId/mm/:colId/exclude', + ncMetaAclMw(mmExcludedList, 'mmExcludedList') +); +router.get( + '/data/:viewId/:rowId/hm/:colId/exclude', + ncMetaAclMw(hmExcludedList, 'hmExcludedList') +); +router.get( + '/data/:viewId/:rowId/bt/:colId/exclude', + ncMetaAclMw(btExcludedList, 'btExcludedList') +); + +router.post( + '/data/:viewId/:rowId/:relationType/:colId/:childId', + ncMetaAclMw(relationDataAdd, 'relationDataAdd') +); +router.delete( + '/data/:viewId/:rowId/:relationType/:colId/:childId', + ncMetaAclMw(relationDataDelete, 'relationDataDelete') +); +export default router; diff --git a/packages/nocodb/src/lib/services/dataService/index.ts b/packages/nocodb/src/lib/services/dataService/index.ts index 27575fe156..42d7a05556 100644 --- a/packages/nocodb/src/lib/services/dataService/index.ts +++ b/packages/nocodb/src/lib/services/dataService/index.ts @@ -227,7 +227,7 @@ export async function dataRead( const row = await baseModel.readByPk(param.rowId); if (!row) { - NcError.notFound(); + NcError.notFound('Row not found'); } return await nocoExecute( @@ -348,3 +348,476 @@ export async function getViewAndModelByAliasOrId(param: { if (!model) NcError.notFound('Table not found'); return { model, view }; } + +export async function dataListByViewId(param: { viewId: string; query: any }) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + return await getDataList({ model, view, query: param.query }); +} + +export async function mmList(param: { + viewId: string; + colId: string; + query: any; + rowId: string; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + const key = `${model.title}List`; + const requestObj: any = { + [key]: 1, + }; + + const data = ( + await nocoExecute( + requestObj, + { + [key]: async (args) => { + return await baseModel.mmList( + { + colId: param.colId, + parentId: param.rowId, + }, + args + ); + }, + }, + {}, + + { nested: { [key]: param.query } } + ) + )?.[key]; + + const count: any = await baseModel.mmListCount({ + colId: param.colId, + parentId: param.rowId, + }); + + return new PagedResponseImpl(data, { + count, + ...param.query, + }); +} + +export async function mmExcludedList(param: { + viewId: string; + colId: string; + query: any; + rowId: string; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + const key = 'List'; + const requestObj: any = { + [key]: 1, + }; + + const data = ( + await nocoExecute( + requestObj, + { + [key]: async (args) => { + return await baseModel.getMmChildrenExcludedList( + { + colId: param.colId, + pid: param.rowId, + }, + args + ); + }, + }, + {}, + + { nested: { [key]: param.query } } + ) + )?.[key]; + + const count = await baseModel.getMmChildrenExcludedListCount( + { + colId: param.colId, + pid: param.rowId, + }, + param.query + ); + + return new PagedResponseImpl(data, { + count, + ...param.query, + }); +} + +export async function hmExcludedList(param: { + viewId: string; + colId: string; + query: any; + rowId: string; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + const key = 'List'; + const requestObj: any = { + [key]: 1, + }; + + const data = ( + await nocoExecute( + requestObj, + { + [key]: async (args) => { + return await baseModel.getHmChildrenExcludedList( + { + colId: param.colId, + pid: param.rowId, + }, + args + ); + }, + }, + {}, + + { nested: { [key]: param.query } } + ) + )?.[key]; + + const count = await baseModel.getHmChildrenExcludedListCount( + { + colId: param.colId, + pid: param.rowId, + }, + param.query + ); + + new PagedResponseImpl(data, { + count, + ...param.query, + }); +} + +export async function btExcludedList(param: { + viewId: string; + colId: string; + query: any; + rowId: string; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) return NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + const key = 'List'; + const requestObj: any = { + [key]: 1, + }; + + const data = ( + await nocoExecute( + requestObj, + { + [key]: async (args) => { + return await baseModel.getBtChildrenExcludedList( + { + colId: param.colId, + cid: param.rowId, + }, + args + ); + }, + }, + {}, + + { nested: { [key]: param.query } } + ) + )?.[key]; + + const count = await baseModel.getBtChildrenExcludedListCount( + { + colId: param.colId, + cid: param.rowId, + }, + param.query + ); + + return new PagedResponseImpl(data, { + count, + ...param.query, + }); +} + +export async function hmList(param: { + viewId: string; + colId: string; + query: any; + rowId: string; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + const key = `${model.title}List`; + const requestObj: any = { + [key]: 1, + }; + + const data = ( + await nocoExecute( + requestObj, + { + [key]: async (args) => { + return await baseModel.hmList( + { + colId: param.colId, + id: param.rowId, + }, + args + ); + }, + }, + {}, + { nested: { [key]: param.query } } + ) + )?.[key]; + + const count = await baseModel.hmListCount({ + colId: param.colId, + id: param.rowId, + }); + + return new PagedResponseImpl(data, { + totalRows: count, + } as any); +} + +export async function dataReadByViewId(param: { + viewId: string; + rowId: string; + query: any; +}) { + try { + const model = await Model.getByIdOrName({ + id: param.viewId, + }); + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + return await nocoExecute( + await getAst({ model, query: param.query }), + await baseModel.readByPk(param.rowId), + {}, + {} + ); + } catch (e) { + console.log(e); + NcError.internalServerError( + 'Internal Server Error, check server log for more details' + ); + } +} + +export async function dataInsertByViewId(param: { + viewId: string; + body: any; + cookie: any; +}) { + const model = await Model.getByIdOrName({ + id: param.viewId, + }); + if (!model) return NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + return await baseModel.insert(param.body, null, param.cookie); +} + +export async function dataUpdateByViewId(param: { + viewId: string; + rowId: string; + body: any; + cookie: any; +}) { + const model = await Model.getByIdOrName({ + id: param.viewId, + }); + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + return await baseModel.updateByPk( + param.rowId, + param.body, + null, + param.cookie + ); +} + +export async function dataDeleteByViewId(param: { + viewId: string; + rowId: string; + cookie: any; +}) { + const model = await Model.getByIdOrName({ + id: param.viewId, + }); + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + return await baseModel.delByPk(param.rowId, null, param.cookie); +} + +export async function relationDataDelete(param: { + viewId: string; + colId: string; + childId: string; + rowId: string; + cookie: any; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + await baseModel.removeChild({ + colId: param.colId, + childId: param.childId, + rowId: param.rowId, + cookie: param.cookie, + }); + + return true; +} + +export async function relationDataAdd(param: { + viewId: string; + colId: string; + childId: string; + rowId: string; + cookie: any; +}) { + const view = await View.get(param.viewId); + + const model = await Model.getByIdOrName({ + id: view?.fk_model_id || param.viewId, + }); + + if (!model) NcError.notFound('Table not found'); + + const base = await Base.get(model.base_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base), + }); + + await baseModel.addChild({ + colId: param.colId, + childId: param.childId, + rowId: param.rowId, + cookie: param.cookie, + }); + + return true; +}