Browse Source

fix: type corrections

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5239/head
Pranav C 2 years ago
parent
commit
f7fdedbca6
  1. 2
      packages/nocodb-sdk/src/lib/Api.ts
  2. 14
      packages/nocodb/package-lock.json
  3. 2
      packages/nocodb/package.json
  4. 8
      packages/nocodb/src/lib/Noco.ts
  5. 25
      packages/nocodb/src/lib/controllers/columnController.ts
  6. 2
      packages/nocodb/src/lib/controllers/dataApis/dataAliasExportApis.ts
  7. 161
      packages/nocodb/src/lib/controllers/dataApis/helpers.ts
  8. 10
      packages/nocodb/src/lib/controllers/dataController/export.ts
  9. 130
      packages/nocodb/src/lib/controllers/hookFilterController.ts
  10. 6
      packages/nocodb/src/lib/controllers/kanbanViewController.ts
  11. 2
      packages/nocodb/src/lib/controllers/orgLicenseController.ts
  12. 11
      packages/nocodb/src/lib/controllers/pluginController.ts
  13. 10
      packages/nocodb/src/lib/controllers/projectController.ts
  14. 6
      packages/nocodb/src/lib/controllers/public/index.ts
  15. 2
      packages/nocodb/src/lib/controllers/sortController.ts
  16. 30
      packages/nocodb/src/lib/controllers/swaggerController/index.ts
  17. 6
      packages/nocodb/src/lib/controllers/sync/helpers/job.ts
  18. 16
      packages/nocodb/src/lib/controllers/sync/syncSourceApis.ts
  19. 2
      packages/nocodb/src/lib/controllers/tableController.ts
  20. 16
      packages/nocodb/src/lib/controllers/userApi/initAdminFromEnv.ts
  21. 30
      packages/nocodb/src/lib/controllers/userApi/userApis.ts
  22. 4
      packages/nocodb/src/lib/controllers/userController/index.ts
  23. 5
      packages/nocodb/src/lib/controllers/viewController.ts
  24. 4
      packages/nocodb/src/lib/db/sql-client/lib/KnexClient.ts
  25. 4
      packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts
  26. 48
      packages/nocodb/src/lib/meta/NcMetaMgr.ts
  27. 8
      packages/nocodb/src/lib/meta/NcMetaMgrEE.ts
  28. 0
      packages/nocodb/src/lib/meta/api/projectApis.ts
  29. 4
      packages/nocodb/src/lib/meta/helpers/apiMetrics.ts
  30. 2
      packages/nocodb/src/lib/models/GalleryView.ts
  31. 166
      packages/nocodb/src/lib/models/Hook.ts
  32. 8
      packages/nocodb/src/lib/models/KanbanView.ts
  33. 577
      packages/nocodb/src/lib/models/Model.ts
  34. 2
      packages/nocodb/src/lib/models/Project.ts
  35. 6
      packages/nocodb/src/lib/services/apiTokenService.ts
  36. 6
      packages/nocodb/src/lib/services/attachmentService.ts
  37. 10
      packages/nocodb/src/lib/services/baseService.ts
  38. 6
      packages/nocodb/src/lib/services/cacheService.ts
  39. 50
      packages/nocodb/src/lib/services/columnService.ts
  40. 30
      packages/nocodb/src/lib/services/dataService/export.ts
  41. 172
      packages/nocodb/src/lib/services/dataService/helpers.ts
  42. 5
      packages/nocodb/src/lib/services/dataService/index.ts
  43. 57
      packages/nocodb/src/lib/services/filterService.ts
  44. 4
      packages/nocodb/src/lib/services/formViewColumnService.ts
  45. 6
      packages/nocodb/src/lib/services/formViewService.ts
  46. 8
      packages/nocodb/src/lib/services/galleryViewService.ts
  47. 4
      packages/nocodb/src/lib/services/gridViewColumnService.ts
  48. 6
      packages/nocodb/src/lib/services/gridViewService.ts
  49. 8
      packages/nocodb/src/lib/services/hookFilterService.ts
  50. 16
      packages/nocodb/src/lib/services/hookService.ts
  51. 6
      packages/nocodb/src/lib/services/kanbanViewService.ts
  52. 25
      packages/nocodb/src/lib/services/mapViewService.ts
  53. 10
      packages/nocodb/src/lib/services/metaDiffService.ts
  54. 6
      packages/nocodb/src/lib/services/modelVisibilityService.ts
  55. 8
      packages/nocodb/src/lib/services/orgLicenseService.ts
  56. 6
      packages/nocodb/src/lib/services/orgTokenService.ts
  57. 4
      packages/nocodb/src/lib/services/orgUserService.ts
  58. 29
      packages/nocodb/src/lib/services/pluginService.ts
  59. 14
      packages/nocodb/src/lib/services/projectService.ts
  60. 4
      packages/nocodb/src/lib/services/projectUserService.ts
  61. 17
      packages/nocodb/src/lib/services/sharedBaseService.ts
  62. 9
      packages/nocodb/src/lib/services/sortService.ts
  63. 2
      packages/nocodb/src/lib/services/swaggerService/getSwaggerJSON.ts
  64. 13
      packages/nocodb/src/lib/services/swaggerService/index.ts
  65. 6
      packages/nocodb/src/lib/services/syncService/helpers/job.ts
  66. 18
      packages/nocodb/src/lib/services/syncService/index.ts
  67. 9
      packages/nocodb/src/lib/services/tableService.ts
  68. 4
      packages/nocodb/src/lib/services/userService/helpers.ts
  69. 87
      packages/nocodb/src/lib/services/userService/index.ts
  70. 15
      packages/nocodb/src/lib/services/userService/initAdminFromEnv.ts
  71. 70
      packages/nocodb/src/lib/services/userService/ui/auth/emailVerify.ts
  72. 108
      packages/nocodb/src/lib/services/userService/ui/auth/resetPassword.ts
  73. 171
      packages/nocodb/src/lib/services/userService/ui/emailTemplates/forgotPassword.ts
  74. 208
      packages/nocodb/src/lib/services/userService/ui/emailTemplates/invite.ts
  75. 207
      packages/nocodb/src/lib/services/userService/ui/emailTemplates/verify.ts
  76. 4
      packages/nocodb/src/lib/services/utilService.ts
  77. 8
      packages/nocodb/src/lib/services/viewColumnService.ts
  78. 32
      packages/nocodb/src/lib/services/viewService.ts
  79. 6
      packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts
  80. 4
      packages/nocodb/src/lib/v1-legacy/NcProjectBuilder.ts
  81. 18
      packages/nocodb/src/lib/v1-legacy/rest/RestAuthCtrl.ts
  82. 4
      packages/nocodb/src/lib/v1-legacy/rest/RestAuthCtrlEE.ts
  83. 6
      packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts

2
packages/nocodb-sdk/src/lib/Api.ts

@ -651,7 +651,7 @@ export interface HookReqType {
env?: string;
event: 'after' | 'before';
operation: 'insert' | 'delete' | 'update';
async?: string | number | null;
async?: BoolType;
notification: object;
retries?: number;
retry_interval?: number;

14
packages/nocodb/package-lock.json generated

@ -65,7 +65,7 @@
"multer": "^1.4.2",
"mysql2": "^2.2.5",
"nanoid": "^3.1.20",
"nc-help": "0.2.85",
"nc-help": "0.2.87",
"nc-lib-gui": "0.105.3",
"nc-plugin": "0.1.2",
"ncp": "^2.0.0",
@ -11294,9 +11294,9 @@
}
},
"node_modules/nc-help": {
"version": "0.2.85",
"resolved": "https://registry.npmjs.org/nc-help/-/nc-help-0.2.85.tgz",
"integrity": "sha512-EOyrc2PuRUJzv73jHNHmUR6YhC0TlJG0DTY/sug7BF4MJAVPJgyavJnrqkRC7g0NS4xociki9gs5MbLRjlRwtQ==",
"version": "0.2.87",
"resolved": "https://registry.npmjs.org/nc-help/-/nc-help-0.2.87.tgz",
"integrity": "sha512-Zlg06ialvylBEE1qtvjlNKxZrPShzXwvy3WG7nfw+8GngOkQBCTlKguejT2Kq4Gfb5378WPX1APXtsetMKBrRA==",
"dependencies": {
"@rudderstack/rudder-sdk-node": "^1.1.3",
"axios": "^0.21.1",
@ -28004,9 +28004,9 @@
"integrity": "sha512-3AryS9uwa5NfISLxMciUonrH7YfXp+nlahB9T7girXIsLQrmwX4MdnuKs32akduCOGpKmjTJSWmATULbuMkbfw=="
},
"nc-help": {
"version": "0.2.85",
"resolved": "https://registry.npmjs.org/nc-help/-/nc-help-0.2.85.tgz",
"integrity": "sha512-EOyrc2PuRUJzv73jHNHmUR6YhC0TlJG0DTY/sug7BF4MJAVPJgyavJnrqkRC7g0NS4xociki9gs5MbLRjlRwtQ==",
"version": "0.2.87",
"resolved": "https://registry.npmjs.org/nc-help/-/nc-help-0.2.87.tgz",
"integrity": "sha512-Zlg06ialvylBEE1qtvjlNKxZrPShzXwvy3WG7nfw+8GngOkQBCTlKguejT2Kq4Gfb5378WPX1APXtsetMKBrRA==",
"requires": {
"@rudderstack/rudder-sdk-node": "^1.1.3",
"axios": "^0.21.1",

2
packages/nocodb/package.json

@ -105,7 +105,7 @@
"multer": "^1.4.2",
"mysql2": "^2.2.5",
"nanoid": "^3.1.20",
"nc-help": "0.2.85",
"nc-help": "0.2.87",
"nc-lib-gui": "0.105.3",
"nc-plugin": "0.1.2",
"ncp": "^2.0.0",

8
packages/nocodb/src/lib/Noco.ts

@ -21,7 +21,7 @@ import { NC_LICENSE_KEY } from './constants';
import Migrator from './db/sql-migrator/lib/KnexMigrator';
import Store from './models/Store';
import NcConfigFactory from './utils/NcConfigFactory';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import NcProjectBuilderCE from './v1-legacy/NcProjectBuilder';
import NcProjectBuilderEE from './v1-legacy/NcProjectBuilderEE';
@ -275,10 +275,10 @@ export default class Noco {
}
next();
});
Tele.init({
T.init({
instance: getInstance,
});
Tele.emit('evt_app_started', await User.count());
T.emit('evt_app_started', await User.count());
console.log(`App started successfully.\nVisit -> ${Noco.dashboardUrl}`);
weAreHiring();
return this.router;
@ -531,7 +531,7 @@ export default class Noco {
if (!serverId) {
await Noco._ncMeta.metaInsert('', '', 'nc_store', {
key: 'nc_server_id',
value: (serverId = Tele.id),
value: (serverId = T.id),
});
}
process.env.NC_SERVER_UUID = serverId;

25
packages/nocodb/src/lib/controllers/columnController.ts

@ -1,8 +1,8 @@
import { Request, Response, Router } from 'express'
import { Request, Response, Router } from 'express';
import { ColumnReqType, TableType, UITypes } from 'nocodb-sdk';
import { getAjvValidatorMw } from '../meta/api/helpers'
import { metaApiMetrics } from '../meta/helpers/apiMetrics'
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw'
import { getAjvValidatorMw } from '../meta/api/helpers';
import { metaApiMetrics } from '../meta/helpers/apiMetrics';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';
import { columnService } from '../services';
export async function columnGet(req: Request, res: Response) {
@ -27,20 +27,19 @@ export async function columnSetAsPrimary(req: Request, res: Response) {
);
}
export async function columnUpdate(req: Request, res: Response<TableType>){
res.json(await columnService.columnUpdate({
columnId: req.params.columnId,
column: req.body
})
export async function columnUpdate(req: Request, res: Response<TableType>) {
res.json(
await columnService.columnUpdate({
columnId: req.params.columnId,
column: req.body,
})
);
}
export async function columnDelete(req: Request, res: Response<TableType>) {
res.json(await columnService.columnDelete({ columnId: req.params.columnId }));
res.json(await columnService.columnDelete({ columnId: req.params.columnId }));
}
const router = Router({ mergeParams: true });
router.post(

2
packages/nocodb/src/lib/controllers/dataApis/dataAliasExportApis.ts

@ -15,7 +15,7 @@ async function excelDataExport(req: Request, res: Response) {
if (!targetView) {
targetView = await View.getDefaultView(model.id);
}
const { offset, elapsed, data } = await extractXlsxData(targetView, req);
const { offset, elapsed, data } = await extractXlsxData({ view: targetView, query: req.query, siteUrl: (req as any).ncSiteUrl });
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, data, targetView.title);
const buf = XLSX.write(wb, { type: 'base64', bookType: 'xlsx' });

161
packages/nocodb/src/lib/controllers/dataApis/helpers.ts

@ -1,20 +1,19 @@
import Project from '../../models/Project';
import Model from '../../models/Model';
import View from '../../models/View';
import { NcError } from '../../meta/helpers/catchError';
import Project from '../../../models/Project';
import Model from '../../../models/Model';
import View from '../../../models/View';
import { NcError } from '../../helpers/catchError';
import { Request } from 'express';
import Base from '../../models/Base';
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2';
import Base from '../../../models/Base';
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2';
import { isSystemColumn, UITypes } from 'nocodb-sdk';
import { nocoExecute } from 'nc-help';
import * as XLSX from 'xlsx';
import Column from '../../models/Column';
import LookupColumn from '../../models/LookupColumn';
import LinkToAnotherRecordColumn from '../../models/LinkToAnotherRecordColumn';
import Column from '../../../models/Column';
import LookupColumn from '../../../models/LookupColumn';
import LinkToAnotherRecordColumn from '../../../models/LinkToAnotherRecordColumn';
import papaparse from 'papaparse';
import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst';
import { dataService } from '../../../services';
export async function getViewAndModelFromRequestByAliasOrId(
req:
| Request<{ projectName: string; tableName: string; viewName?: string }>
@ -36,8 +35,12 @@ export async function getViewAndModelFromRequestByAliasOrId(
return { model, view };
}
export async function extractXlsxData(param: {view: View, query:any}) {
const { view, query } = param;
export async function extractXlsxData(param: {
view: View;
query: any;
siteUrl: string;
}) {
const { view, query, siteUrl } = param;
const base = await Base.get(view.base_id);
await view.getModelWithInfo();
@ -57,9 +60,14 @@ export async function extractXlsxData(param: {view: View, query:any}) {
dbDriver: NcConnectionMgrv2.get(base),
});
const { offset, dbRows, elapsed } = await getDbRows(baseModel, view, req);
const { offset, dbRows, elapsed } = await dataService.getDbRows({
baseModel,
view,
query,
siteUrl,
});
const fields = req.query.fields as string[];
const fields = query.fields as string[];
const data = XLSX.utils.json_to_sheet(dbRows, { header: fields });
@ -87,7 +95,12 @@ export async function extractCsvData(view: View, req: Request) {
dbDriver: NcConnectionMgrv2.get(base),
});
const { offset, dbRows, elapsed } = await getDbRows(baseModel, view, req);
const { offset, dbRows, elapsed } = await dataService.getDbRows({
baseModel,
view,
query: req.query,
siteUrl: (req as any).ncSiteUrl,
});
const data = papaparse.unparse(
{
@ -111,64 +124,64 @@ export async function extractCsvData(view: View, req: Request) {
return { offset, dbRows, elapsed, data };
}
async function getDbRows(baseModel, view: View, req: Request) {
let offset = +req.query.offset || 0;
const limit = 100;
// const size = +process.env.NC_EXPORT_MAX_SIZE || 1024;
const timeout = +process.env.NC_EXPORT_MAX_TIMEOUT || 5000;
const dbRows = [];
const startTime = process.hrtime();
let elapsed, temp;
const listArgs: any = { ...req.query };
try {
listArgs.filterArr = JSON.parse(listArgs.filterArrJson);
} catch (e) {}
try {
listArgs.sortArr = JSON.parse(listArgs.sortArrJson);
} catch (e) {}
for (
elapsed = 0;
elapsed < timeout;
offset += limit,
temp = process.hrtime(startTime),
elapsed = temp[0] * 1000 + temp[1] / 1000000
) {
const rows = await nocoExecute(
await getAst({
query: req.query,
includePkByDefault: false,
model: view.model,
view,
}),
await baseModel.list({ ...listArgs, offset, limit }),
{},
req.query
);
if (!rows?.length) {
offset = -1;
break;
}
for (const row of rows) {
const dbRow = { ...row };
for (const column of view.model.columns) {
if (isSystemColumn(column) && !view.show_system_fields) continue;
dbRow[column.title] = await serializeCellValue({
value: row[column.title],
column,
siteUrl: req['ncSiteUrl'],
});
}
dbRows.push(dbRow);
}
}
return { offset, dbRows, elapsed };
}
//
// async function getDbRows(baseModel, view: View, req: Request) {
// let offset = +req.query.offset || 0;
// const limit = 100;
// // const size = +process.env.NC_EXPORT_MAX_SIZE || 1024;
// const timeout = +process.env.NC_EXPORT_MAX_TIMEOUT || 5000;
// const dbRows = [];
// const startTime = process.hrtime();
// let elapsed, temp;
//
// const listArgs: any = { ...req.query };
// try {
// listArgs.filterArr = JSON.parse(listArgs.filterArrJson);
// } catch (e) {}
// try {
// listArgs.sortArr = JSON.parse(listArgs.sortArrJson);
// } catch (e) {}
//
// for (
// elapsed = 0;
// elapsed < timeout;
// offset += limit,
// temp = process.hrtime(startTime),
// elapsed = temp[0] * 1000 + temp[1] / 1000000
// ) {
// const rows = await nocoExecute(
// await getAst({
// query: req.query,
// includePkByDefault: false,
// model: view.model,
// view,
// }),
// await baseModel.list({ ...listArgs, offset, limit }),
// {},
// req.query
// );
//
// if (!rows?.length) {
// offset = -1;
// break;
// }
//
// for (const row of rows) {
// const dbRow = { ...row };
//
// for (const column of view.model.columns) {
// if (isSystemColumn(column) && !view.show_system_fields) continue;
// dbRow[column.title] = await serializeCellValue({
// value: row[column.title],
// column,
// siteUrl: req['ncSiteUrl'],
// });
// }
// dbRows.push(dbRow);
// }
// }
// return { offset, dbRows, elapsed };
// }
export async function serializeCellValue({
value,

10
packages/nocodb/src/lib/controllers/dataController/export.ts

@ -1,13 +1,13 @@
import { Request, Response, Router } from 'express';
import * as XLSX from 'xlsx';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import { getViewAndModelFromRequestByAliasOrId } from '../../meta/api/dataApis/helpers';
import apiMetrics from '../../meta/helpers/apiMetrics';
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw';
import { View } from '../../models';
import {
extractCsvData,
extractXlsxData,
getViewAndModelFromRequestByAliasOrId,
} from './helpers';
import apiMetrics from '../../helpers/apiMetrics';
import View from '../../../models/View';
} from '../../services/dataService/helpers';
async function excelDataExport(req: Request, res: Response) {
const { model, view } = await getViewAndModelFromRequestByAliasOrId(req);

130
packages/nocodb/src/lib/controllers/hookFilterController.ts

@ -1,112 +1,60 @@
import { Request, Response, Router } from 'express';
// @ts-ignore
import Model from '../models/Model';
import { Tele } from 'nc-help';
// @ts-ignore
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
// @ts-ignore
import { Table, TableList, TableListParams, TableReq } from 'nocodb-sdk';
// @ts-ignore
import ProjectMgrv2 from '../db/sql-mgr/v2/ProjectMgrv2';
// @ts-ignore
import Project from '../models/Project';
import Filter from '../models/Filter';
import { T } from 'nc-help';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';
import { metaApiMetrics } from '../meta/helpers/apiMetrics';
import { getAjvValidatorMw } from '../meta/api/helpers';
import { hookFilterService } from '../services';
// @ts-ignore
export async function filterGet(req: Request, res: Response, next) {
try {
const filter = await Filter.getFilterObject({ hookId: req.params.hookId });
export async function filterGet(req: Request, res: Response) {
const filter = await hookFilterService.filterGet({
hookId: req.params.hookId,
});
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
res.json(filter);
}
// @ts-ignore
export async function filterList(
req: Request<any, any, any, TableListParams>,
res: Response,
next
) {
try {
const filter = await Filter.rootFilterListByHook({
hookId: req.params.hookId,
});
export async function filterList(req: Request, res: Response) {
const filter = await hookFilterService.filterList({
hookId: req.params.hookId,
});
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
res.json(filter);
}
// @ts-ignore
export async function filterChildrenRead(
req: Request<any, any, any, TableListParams>,
res: Response,
next
) {
try {
const filter = await Filter.parentFilterListByHook({
hookId: req.params.hookId,
parentId: req.params.filterParentId,
});
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
export async function filterChildrenRead(req: Request, res: Response) {
const filter = await hookFilterService.filterChildrenRead({
hookId: req.params.hookId,
filterParentId: req.params.filterParentId,
});
res.json(filter);
}
export async function filterCreate(
req: Request<any, any, TableReq>,
res,
next
) {
try {
const filter = await Filter.insert({
...req.body,
fk_hook_id: req.params.hookId,
});
export async function filterCreate(req: Request<any, any>, res) {
const filter = await hookFilterService.filterCreate({
filter: req.body,
hookId: req.params.hookId,
});
Tele.emit('evt', { evt_type: 'hookFilter:created' });
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
res.json(filter);
}
// @ts-ignore
export async function filterUpdate(req, res, next) {
try {
const filter = await Filter.update(req.params.filterId, {
...req.body,
fk_hook_id: req.params.hookId,
});
Tele.emit('evt', { evt_type: 'hookFilter:updated' });
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
export async function filterUpdate(req, res) {
const filter = await hookFilterService.filterUpdate({
filterId: req.params.filterId,
filter: req.body,
hookId: req.params.hookId,
});
res.json(filter);
}
// @ts-ignore
export async function filterDelete(req: Request, res: Response, next) {
try {
const filter = await Filter.delete(req.params.filterId);
Tele.emit('evt', { evt_type: 'hookFilter:deleted' });
res.json(filter);
} catch (e) {
console.log(e);
next(e);
}
export async function filterDelete(req: Request, res: Response) {
const filter = await hookFilterService.filterDelete({
filterId: req.params.filterId,
});
T.emit('evt', { evt_type: 'hookFilter:deleted' });
res.json(filter);
}
const router = Router({ mergeParams: true });

6
packages/nocodb/src/lib/controllers/kanbanViewController.ts

@ -2,7 +2,7 @@ import { Request, Response, Router } from 'express';
import { KanbanType, ViewTypes } from 'nocodb-sdk';
import View from '../models/View';
import KanbanView from '../models/KanbanView';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';
import { metaApiMetrics } from '../meta/helpers/apiMetrics';
import { getAjvValidatorMw } from '../meta/api/helpers';
@ -12,7 +12,7 @@ export async function kanbanViewGet(req: Request, res: Response<KanbanType>) {
}
export async function kanbanViewCreate(req: Request<any, any>, res) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'kanban' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'kanban' });
const view = await View.insert({
...req.body,
// todo: sanitize
@ -23,7 +23,7 @@ export async function kanbanViewCreate(req: Request<any, any>, res) {
}
export async function kanbanViewUpdate(req, res) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'kanban' });
T.emit('evt', { evt_type: 'view:updated', type: 'kanban' });
res.json(await KanbanView.update(req.params.kanbanViewId, req.body));
}

2
packages/nocodb/src/lib/controllers/orgLicenseController.ts

@ -10,7 +10,7 @@ async function licenseGet(_req, res) {
}
async function licenseSet(req, res) {
await orgLicenseService.licenseSet({ key: req.body.key })
await orgLicenseService.licenseSet({ key: req.body.key });
res.json({ msg: 'License key saved' });
}

11
packages/nocodb/src/lib/controllers/pluginController.ts

@ -6,8 +6,6 @@ import { metaApiMetrics } from '../meta/helpers/apiMetrics';
import { getAjvValidatorMw } from '../meta/api/helpers';
import { pluginService } from '../services';
export async function pluginList(_req: Request, res: Response) {
res.json(new PagedResponseImpl(await pluginService.pluginList()));
}
@ -23,11 +21,16 @@ export async function pluginUpdate(
req: Request<any, any, PluginType>,
res: Response
) {
const plugin = await pluginService.pluginUpdate({ pluginId: req.params.pluginId, plugin:req.body });
const plugin = await pluginService.pluginUpdate({
pluginId: req.params.pluginId,
plugin: req.body,
});
res.json(plugin);
}
export async function isPluginActive(req: Request, res: Response) {
res.json(await pluginService.isPluginActive({ pluginTitle: req.params.pluginTitle }));
res.json(
await pluginService.isPluginActive({ pluginTitle: req.params.pluginTitle })
);
}
const router = Router({ mergeParams: true });

10
packages/nocodb/src/lib/controllers/projectController.ts

@ -3,7 +3,7 @@ import { ProjectType } from 'nocodb-sdk';
import Project from '../models/Project';
import { ProjectListType } from 'nocodb-sdk';
import { packageVersion } from '../utils/packageVersion';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';
@ -60,10 +60,7 @@ export async function projectList(
);
}
export async function projectDelete(
req: Request<any>,
res: Response<boolean>
) {
export async function projectDelete(req: Request<any>, res: Response<boolean>) {
const deleted = await projectService.projectSoftDelete({
projectId: req.params.projectId,
});
@ -71,7 +68,6 @@ export async function projectDelete(
res.json(deleted);
}
async function projectCreate(req: Request<any, any>, res) {
const project = await projectService.projectCreate({
project: req.body,
@ -116,7 +112,7 @@ export async function projectCost(req, res) {
}
}
Tele.event({
T.event({
event: 'a:project:cost',
data: {
cost,

6
packages/nocodb/src/lib/controllers/public/index.ts

@ -2,4 +2,8 @@ import publicDataController from './publicDataApis';
import publicDataExportController from './publicDataExportApis';
import publicMetaController from './publicMetaApis';
export { publicDataController, publicDataExportController, publicMetaController };
export {
publicDataController,
publicDataExportController,
publicMetaController,
};

2
packages/nocodb/src/lib/controllers/sortController.ts

@ -1,5 +1,5 @@
import { Request, Response, Router } from 'express';
import { getAjvValidatorMw } from '../meta/api/helpers'
import { getAjvValidatorMw } from '../meta/api/helpers';
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
import { SortListType, SortReqType } from 'nocodb-sdk';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';

30
packages/nocodb/src/lib/controllers/swaggerController/index.ts

@ -1,36 +1,36 @@
import { Router } from 'express'
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw'
import getSwaggerHtml from './swaggerHtml'
import getRedocHtml from './redocHtml'
import { swaggerService } from '../../services'
import { Router } from 'express';
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw';
import getSwaggerHtml from './swaggerHtml';
import getRedocHtml from './redocHtml';
import { swaggerService } from '../../services';
async function swaggerJson(req, res) {
const swagger = await swaggerService.swaggerJson({
projectId: req.params.projectId,
siteUrl: req.ncSiteUrl,
})
});
res.json(swagger)
res.json(swagger);
}
function swaggerHtml(_, res) {
res.send(getSwaggerHtml({ ncSiteUrl: process.env.NC_PUBLIC_URL || '' }))
res.send(getSwaggerHtml({ ncSiteUrl: process.env.NC_PUBLIC_URL || '' }));
}
function redocHtml(_, res) {
res.send(getRedocHtml({ ncSiteUrl: process.env.NC_PUBLIC_URL || '' }))
res.send(getRedocHtml({ ncSiteUrl: process.env.NC_PUBLIC_URL || '' }));
}
const router = Router({ mergeParams: true })
const router = Router({ mergeParams: true });
// todo: auth
router.get(
'/api/v1/db/meta/projects/:projectId/swagger.json',
ncMetaAclMw(swaggerJson, 'swaggerJson'),
)
ncMetaAclMw(swaggerJson, 'swaggerJson')
);
router.get('/api/v1/db/meta/projects/:projectId/swagger', swaggerHtml)
router.get('/api/v1/db/meta/projects/:projectId/swagger', swaggerHtml);
router.get('/api/v1/db/meta/projects/:projectId/redoc', redocHtml)
router.get('/api/v1/db/meta/projects/:projectId/redoc', redocHtml);
export default router
export default router;

6
packages/nocodb/src/lib/controllers/sync/helpers/job.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import FetchAT from './fetchAT';
import { UITypes } from 'nocodb-sdk';
// import * as sMap from './syncMap';
@ -1924,7 +1924,7 @@ export default async (
});
}
Tele.event({
T.event({
event: 'a:airtable-import:success',
data: {
stats: {
@ -2391,7 +2391,7 @@ export default async (
}
} catch (e) {
if (e.response?.data?.msg) {
Tele.event({
T.event({
event: 'a:airtable-import:error',
data: { error: e.response.data.msg },
});

16
packages/nocodb/src/lib/controllers/sync/syncSourceApis.ts

@ -1,10 +1,10 @@
import { Request, Response, Router } from 'express';
import SyncSource from '../../models/SyncSource';
import { Tele } from 'nc-help';
import { PagedResponseImpl } from '../../meta/helpers/PagedResponse';
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw';
import Project from '../../models/Project';
import SyncSource from '../../../models/SyncSource';
import { T } from 'nc-help';
import { PagedResponseImpl } from '../../helpers/PagedResponse';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import Project from '../../../models/Project';
export async function syncSourceList(req: Request, res: Response) {
// todo: pagination
@ -16,7 +16,7 @@ export async function syncSourceList(req: Request, res: Response) {
}
export async function syncCreate(req: Request, res: Response) {
Tele.emit('evt', { evt_type: 'webhooks:created' });
T.emit('evt', { evt_type: 'webhooks:created' });
const project = await Project.getWithInfo(req.params.projectId);
const sync = await SyncSource.insert({
@ -29,12 +29,12 @@ export async function syncCreate(req: Request, res: Response) {
}
export async function syncDelete(req: Request, res: Response<any>) {
Tele.emit('evt', { evt_type: 'webhooks:deleted' });
T.emit('evt', { evt_type: 'webhooks:deleted' });
res.json(await SyncSource.delete(req.params.syncId));
}
export async function syncUpdate(req: Request, res: Response) {
Tele.emit('evt', { evt_type: 'webhooks:updated' });
T.emit('evt', { evt_type: 'webhooks:updated' });
res.json(await SyncSource.update(req.params.syncId, req.body));
}

2
packages/nocodb/src/lib/controllers/tableController.ts

@ -42,7 +42,7 @@ export async function tableGet(req: Request, res: Response<TableType>) {
}
export async function tableDelete(req: Request, res: Response) {
const result = await tableService.deleteTable({
const result = await tableService.tableDelete({
tableId: req.params.tableId,
user: (req as any).session?.passport?.user,
});

16
packages/nocodb/src/lib/controllers/userApi/initAdminFromEnv.ts

@ -1,15 +1,15 @@
import User from '../../models/User';
import User from '../../../models/User';
import { v4 as uuidv4 } from 'uuid';
import { promisify } from 'util';
import bcrypt from 'bcryptjs';
import Noco from '../../Noco';
import { CacheScope, MetaTable } from '../../utils/globals';
import ProjectUser from '../../models/ProjectUser';
import Noco from '../../../Noco';
import { CacheScope, MetaTable } from '../../../utils/globals';
import ProjectUser from '../../../models/ProjectUser';
import { validatePassword } from 'nocodb-sdk';
import boxen from 'boxen';
import NocoCache from '../../cache/NocoCache';
import { Tele } from 'nc-help';
import NocoCache from '../../../cache/NocoCache';
import { T } from 'nc-help';
const { isEmail } = require('validator');
const rolesLevel = { owner: 0, creator: 1, editor: 2, commenter: 3, viewer: 4 };
@ -68,7 +68,7 @@ export default async function initAdminFromEnv(_ncMeta = Noco.ncMeta) {
// if super admin not present
if (await User.isFirst(ncMeta)) {
// roles = 'owner,creator,editor'
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
@ -126,7 +126,7 @@ export default async function initAdminFromEnv(_ncMeta = Noco.ncMeta) {
ncMeta
);
} else {
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});

30
packages/nocodb/src/lib/controllers/userApi/userApis.ts

@ -1,30 +1,30 @@
import { Request, Response } from 'express';
import { TableType, validatePassword } from 'nocodb-sdk';
import { OrgUserRoles } from 'nocodb-sdk';
import { NC_APP_SETTINGS } from '../../constants';
import Store from '../../models/Store';
import { Tele } from 'nc-help';
import catchError, { NcError } from '../../meta/helpers/catchError';
import { NC_APP_SETTINGS } from '../../../constants';
import Store from '../../../models/Store';
import { T } from 'nc-help';
import catchError, { NcError } from '../../helpers/catchError';
const { isEmail } = require('validator');
import * as ejs from 'ejs';
import bcrypt from 'bcryptjs';
import { promisify } from 'util';
import User from '../../models/User';
import User from '../../../models/User';
const { v4: uuidv4 } = require('uuid');
import Audit from '../../models/Audit';
import NcPluginMgrv2 from '../../meta/helpers/NcPluginMgrv2';
import Audit from '../../../models/Audit';
import NcPluginMgrv2 from '../../helpers/NcPluginMgrv2';
import passport from 'passport';
import extractProjectIdAndAuthenticate from '../../meta/helpers/extractProjectIdAndAuthenticate';
import ncMetaAclMw from '../../meta/helpers/ncMetaAclMw';
import { MetaTable } from '../../utils/globals';
import Noco from '../../Noco';
import { getAjvValidatorMw } from '../../meta/api/helpers';
import extractProjectIdAndAuthenticate from '../../helpers/extractProjectIdAndAuthenticate';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import { MetaTable } from '../../../utils/globals';
import Noco from '../../../Noco';
import { getAjvValidatorMw } from '../helpers';
import { genJwt } from './helpers';
import { randomTokenString } from '../../meta/helpers/stringHelpers';
import { randomTokenString } from '../../helpers/stringHelpers';
export async function registerNewUserIfAllowed({
firstname,
@ -47,7 +47,7 @@ export async function registerNewUserIfAllowed({
roles = `${OrgUserRoles.CREATOR},${OrgUserRoles.SUPER_ADMIN}`;
// todo: update in nc_store
// roles = 'owner,creator,editor'
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
@ -122,7 +122,7 @@ export async function signup(req: Request, res: Response<TableType>) {
const email_verification_token = uuidv4();
if (!ignore_subscribe) {
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
}
if (user) {

4
packages/nocodb/src/lib/controllers/userController/index.ts

@ -1,6 +1,6 @@
import { Request, Response } from 'express';
import { TableType, validatePassword } from 'nocodb-sdk';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
const { isEmail } = require('validator');
import * as ejs from 'ejs';
@ -64,7 +64,7 @@ export async function signup(req: Request, res: Response<TableType>) {
const email_verification_token = uuidv4();
if (!ignore_subscribe) {
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
}
if (user) {

5
packages/nocodb/src/lib/controllers/viewController.ts

@ -9,10 +9,7 @@ import { viewService } from '../services';
export async function viewGet(req: Request, res: Response) {}
// @ts-ignore
export async function viewList(
req: Request<any, any, any>,
res: Response
) {
export async function viewList(req: Request<any, any, any>, res: Response) {
const filteredViewList = await viewService.viewList({
tableId: req.params.tableId,
user: (req as any).session?.passport?.user,

4
packages/nocodb/src/lib/db/sql-client/lib/KnexClient.ts

@ -1,6 +1,6 @@
/* eslint-disable no-constant-condition */
import { knex, Knex } from 'knex';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import Debug from '../../util/Debug';
import Emit from '../../util/emit';
import Result from '../../util/Result';
@ -620,7 +620,7 @@ class KnexClient extends SqlClient {
KnexClient.___ext = await this._validateInput();
}
if (!KnexClient.___ext) {
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:external',
payload: null,
check: true,

4
packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts

@ -7,7 +7,7 @@ import fsExtra from 'fs-extra';
import importFresh from 'import-fresh';
import inflection from 'inflection';
import slash from 'slash';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import SqlClientFactory from '../sql-client/lib/SqlClientFactory';
// import debug from 'debug';
@ -1047,7 +1047,7 @@ export default class SqlMgr {
// t = process.hrtime();
const data = await require('axios')(...apiMeta);
Tele.emit('evt', { evt_type: 'import:excel:url' });
T.emit('evt', { evt_type: 'import:excel:url' });
return data.data;
}

48
packages/nocodb/src/lib/meta/NcMetaMgr.ts

@ -40,7 +40,7 @@ import NcTemplateParser from '../v1-legacy/templates/NcTemplateParser';
import { defaultConnectionConfig } from '../utils/NcConfigFactory';
import xcMetaDiff from './handlers/xcMetaDiff';
import { UITypes } from 'nocodb-sdk';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { NC_ATTACHMENT_FIELD_SIZE } from '../constants';
const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 10);
const XC_PLUGIN_DET = 'XC_PLUGIN_DET';
@ -953,7 +953,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'webhooks:deleted' });
T.emit('evt', { evt_type: 'webhooks:deleted' });
} catch (e) {
throw e;
}
@ -988,7 +988,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'webhooks:updated' });
T.emit('evt', { evt_type: 'webhooks:updated' });
} else {
const res = await this.xcMeta.metaInsert(
projectId,
@ -1009,7 +1009,7 @@ export default class NcMetaMgr {
description: `created webhook ${args.args.data.title} - ${args.args.data.event} ${args.args.data.operation} - ${args.args.data.notification?.type} - of table ${args.args.tn} `,
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'webhooks:created' });
T.emit('evt', { evt_type: 'webhooks:created' });
return res;
}
@ -1269,7 +1269,7 @@ export default class NcMetaMgr {
} catch (e) {
throw e;
} finally {
Tele.emit('evt', { evt_type: 'image:uploaded' });
T.emit('evt', { evt_type: 'image:uploaded' });
}
}
@ -1595,7 +1595,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'project:created' });
T.emit('evt', { evt_type: 'project:created' });
break;
case 'projectUpdateByWeb':
@ -1603,7 +1603,7 @@ export default class NcMetaMgr {
this.getProjectId(args),
args.args.projectJson
);
Tele.emit('evt', { evt_type: 'project:updated' });
T.emit('evt', { evt_type: 'project:updated' });
break;
case 'projectCreateByOneClick':
{
@ -1635,7 +1635,7 @@ export default class NcMetaMgr {
description: `created project ${config.title}(${result.id}) `,
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'project:created', oneClick: true });
T.emit('evt', { evt_type: 'project:created', oneClick: true });
}
break;
case 'projectCreateByWebWithXCDB': {
@ -1689,10 +1689,10 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'project:created', xcdb: true });
T.emit('evt', { evt_type: 'project:created', xcdb: true });
postListenerCb = async () => {
if (args?.args?.template) {
Tele.emit('evt', {
T.emit('evt', {
evt_type: args.args?.quickImport
? 'project:created:fromExcel'
: 'project:created:fromTemplate',
@ -1730,7 +1730,7 @@ export default class NcMetaMgr {
case 'projectDelete':
case 'projectRestart':
case 'projectStart':
Tele.emit('evt', { evt_type: 'project:' + args.api });
T.emit('evt', { evt_type: 'project:' + args.api });
result = null;
break;
@ -2145,7 +2145,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'acl:updated' });
T.emit('evt', { evt_type: 'acl:updated' });
return res;
} catch (e) {
@ -3485,7 +3485,7 @@ export default class NcMetaMgr {
['id', 'view_id', 'view_type']
);
res.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/view/${res.view_id}`;
Tele.emit('evt', { evt_type: 'sharedView:generated-link' });
T.emit('evt', { evt_type: 'sharedView:generated-link' });
return res;
} catch (e) {
console.log(e);
@ -3549,7 +3549,7 @@ export default class NcMetaMgr {
sharedBase.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/base/${sharedBase.shared_base_id}`;
Tele.emit('evt', { evt_type: 'sharedBase:generated-link' });
T.emit('evt', { evt_type: 'sharedBase:generated-link' });
return sharedBase;
} catch (e) {
console.log(e);
@ -3606,7 +3606,7 @@ export default class NcMetaMgr {
// await this.xcMeta.metaUpdate(this.getProjectId(args), this.getDbAlias(args), 'nc_shared_views', {
// password: args.args?.password
// }, args.args.id);
// Tele.emit('evt', {evt_type: 'sharedView:password-updated'})
// T.emit('evt', {evt_type: 'sharedView:password-updated'})
// return {msg: 'Success'};
// } catch (e) {
// console.log(e)
@ -3623,7 +3623,7 @@ export default class NcMetaMgr {
'nc_shared_views',
args.args.id
);
Tele.emit('evt', { evt_type: 'sharedView:deleted' });
T.emit('evt', { evt_type: 'sharedView:deleted' });
return { msg: 'Success' };
} catch (e) {
console.log(e);
@ -4477,7 +4477,7 @@ export default class NcMetaMgr {
});
}
Tele.emit('evt', { evt_type: 'template:imported' });
T.emit('evt', { evt_type: 'template:imported' });
return result;
}
@ -5071,7 +5071,7 @@ export default class NcMetaMgr {
} catch (e) {
throw e;
} finally {
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'plugin:installed',
title: args.args.title,
});
@ -5153,7 +5153,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'vtable:created',
show_as: args.args.show_as,
});
@ -5270,7 +5270,7 @@ export default class NcMetaMgr {
});
await RestAuthCtrl.instance.loadLatestApiTokens();
Tele.emit('evt', { evt_type: 'apiToken:created' });
T.emit('evt', { evt_type: 'apiToken:created' });
return {
description: args.args.description,
token,
@ -5282,7 +5282,7 @@ export default class NcMetaMgr {
}
protected async xcApiTokenDelete(args): Promise<any> {
Tele.emit('evt', { evt_type: 'apiToken:deleted' });
T.emit('evt', { evt_type: 'apiToken:deleted' });
const res = await this.xcMeta.metaDelete(
null,
null,
@ -5327,7 +5327,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'vtable:renamed',
show_as: args.args.show_as,
});
@ -5335,7 +5335,7 @@ export default class NcMetaMgr {
}
protected async xcVirtualTableUpdate(args): Promise<any> {
// Tele.emit('evt', {evt_type: 'vtable:updated',show_as: args.args.show_as})
// T.emit('evt', {evt_type: 'vtable:updated',show_as: args.args.show_as})
return this.xcMeta.metaUpdate(
this.getProjectId(args),
this.getDbAlias(args),
@ -5482,7 +5482,7 @@ export default class NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'vtable:deleted' });
T.emit('evt', { evt_type: 'vtable:deleted' });
return res;
}

8
packages/nocodb/src/lib/meta/NcMetaMgrEE.ts

@ -1,5 +1,5 @@
import { v4 as uuidv4 } from 'uuid';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import NcMetaMgr from './NcMetaMgr';
@ -104,7 +104,7 @@ export default class NcMetaMgrEE extends NcMetaMgr {
ip: req.clientIp,
});
Tele.emit('evt', { evt_type: 'acl:updated' });
T.emit('evt', { evt_type: 'acl:updated' });
return res;
} catch (e) {
@ -277,7 +277,7 @@ export default class NcMetaMgrEE extends NcMetaMgr {
sharedView.url = `${req.ncSiteUrl}${this.config.dashboardPath}#/nc/view/${sharedView.view_id}`;
}
Tele.emit('evt', { evt_type: 'sharedView:generated-link' });
T.emit('evt', { evt_type: 'sharedView:generated-link' });
return sharedView;
} catch (e) {
console.log(e);
@ -295,7 +295,7 @@ export default class NcMetaMgrEE extends NcMetaMgr {
},
args.args.id
);
Tele.emit('evt', { evt_type: 'sharedView:password-updated' });
T.emit('evt', { evt_type: 'sharedView:password-updated' });
return { msg: 'Success' };
} catch (e) {
console.log(e);

0
packages/nocodb/src/lib/meta/api/projectApis.ts

4
packages/nocodb/src/lib/meta/helpers/apiMetrics.ts

@ -1,5 +1,5 @@
import { Request } from 'express';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
const countMap = {};
@ -9,7 +9,7 @@ const metrics = async (req: Request, c = 150) => {
const event = `a:api:${req.route.path}:${req.method}`;
countMap[event] = (countMap[event] || 0) + 1;
if (countMap[event] >= c) {
Tele.event({ event });
T.event({ event });
countMap[event] = 0;
}
};

2
packages/nocodb/src/lib/models/GalleryView.ts

@ -1,6 +1,6 @@
import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { BoolType, GalleryColumnType, GalleryType, UITypes } from 'nocodb-sdk'
import { BoolType, GalleryColumnType, GalleryType, UITypes } from 'nocodb-sdk';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';

166
packages/nocodb/src/lib/models/Hook.ts

@ -1,42 +1,42 @@
import { BoolType, HookType } from 'nocodb-sdk'
import { BoolType, HookReqType, HookType } from 'nocodb-sdk'
import {
CacheDelDirection,
CacheGetType,
CacheScope,
MetaTable,
} from '../utils/globals';
import Noco from '../Noco';
import Model from './Model';
import NocoCache from '../cache/NocoCache';
import Filter from './Filter';
import HookFilter from './HookFilter';
import { extractProps } from '../meta/helpers/extractProps';
} from '../utils/globals'
import Noco from '../Noco'
import Model from './Model'
import NocoCache from '../cache/NocoCache'
import Filter from './Filter'
import HookFilter from './HookFilter'
import { extractProps } from '../meta/helpers/extractProps'
export default class Hook implements HookType {
id?: string;
fk_model_id?: string;
title?: string;
description?: string;
env?: string;
type?: string;
event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update';
async?: BoolType;
payload?: string;
url?: string;
headers?: string;
condition?: BoolType;
notification?: string;
retries?: number;
retry_interval?: number;
timeout?: number;
active?: BoolType;
id?: string
fk_model_id?: string
title?: string
description?: string
env?: string
type?: string
event?: 'after' | 'before'
operation?: 'insert' | 'delete' | 'update'
async?: BoolType
payload?: string
url?: string
headers?: string
condition?: BoolType
notification?: string
retries?: number
retry_interval?: number
timeout?: number
active?: BoolType
project_id?: string;
base_id?: string;
project_id?: string
base_id?: string
constructor(hook: Partial<Hook>) {
Object.assign(this, hook);
constructor(hook: Partial<Hook | HookReqType>) {
Object.assign(this, hook)
}
public static async get(hookId: string, ncMeta = Noco.ncMeta) {
@ -44,17 +44,17 @@ export default class Hook implements HookType {
hookId &&
(await NocoCache.get(
`${CacheScope.HOOK}:${hookId}`,
CacheGetType.TYPE_OBJECT
));
CacheGetType.TYPE_OBJECT,
))
if (!hook) {
hook = await ncMeta.metaGet2(null, null, MetaTable.HOOKS, hookId);
await NocoCache.set(`${CacheScope.HOOK}:${hookId}`, hook);
hook = await ncMeta.metaGet2(null, null, MetaTable.HOOKS, hookId)
await NocoCache.set(`${CacheScope.HOOK}:${hookId}`, hook)
}
return hook && new Hook(hook);
return hook && new Hook(hook)
}
public async getFilters(ncMeta = Noco.ncMeta) {
return await Filter.rootFilterListByHook({ hookId: this.id }, ncMeta);
return await Filter.rootFilterListByHook({ hookId: this.id }, ncMeta)
}
// public static async insert(hook: Partial<Hook>) {
@ -81,9 +81,9 @@ export default class Hook implements HookType {
event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update';
},
ncMeta = Noco.ncMeta
ncMeta = Noco.ncMeta,
) {
let hooks = await NocoCache.getList(CacheScope.HOOK, [param.fk_model_id]);
let hooks = await NocoCache.getList(CacheScope.HOOK, [param.fk_model_id])
if (!hooks.length) {
hooks = await ncMeta.metaList(null, null, MetaTable.HOOKS, {
condition: {
@ -96,31 +96,29 @@ export default class Hook implements HookType {
orderBy: {
created_at: 'asc',
},
});
await NocoCache.setList(CacheScope.HOOK, [param.fk_model_id], hooks);
})
await NocoCache.setList(CacheScope.HOOK, [param.fk_model_id], hooks)
}
// filter event & operation
if (param.event) {
hooks = hooks.filter(
(h) => h.event?.toLowerCase() === param.event?.toLowerCase()
);
(h) => h.event?.toLowerCase() === param.event?.toLowerCase(),
)
}
if (param.operation) {
hooks = hooks.filter(
(h) => h.operation?.toLowerCase() === param.operation?.toLowerCase()
);
(h) => h.operation?.toLowerCase() === param.operation?.toLowerCase(),
)
}
return hooks?.map((h) => new Hook(h));
return hooks?.map((h) => new Hook(h))
}
public static async insert(
hook: Partial<
Hook & {
created_at?;
updated_at?;
}
>,
ncMeta = Noco.ncMeta
hook: Partial<Hook & {
created_at?;
updated_at?;
}>,
ncMeta = Noco.ncMeta,
) {
const insertObj = extractProps(hook, [
'fk_model_id',
@ -142,49 +140,49 @@ export default class Hook implements HookType {
'base_id',
'created_at',
'updated_at',
]);
])
if (insertObj.event) {
insertObj.event = insertObj.event.toLowerCase() as 'after' | 'before';
insertObj.event = insertObj.event.toLowerCase() as 'after' | 'before'
}
if (insertObj.operation) {
insertObj.operation = insertObj.operation.toLowerCase() as
| 'insert'
| 'delete'
| 'update';
| 'update'
}
if (insertObj.notification && typeof insertObj.notification === 'object') {
insertObj.notification = JSON.stringify(insertObj.notification);
insertObj.notification = JSON.stringify(insertObj.notification)
}
if (!(hook.project_id && hook.base_id)) {
const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta);
insertObj.project_id = model.project_id;
insertObj.base_id = model.base_id;
const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta)
insertObj.project_id = model.project_id
insertObj.base_id = model.base_id
}
const { id } = await ncMeta.metaInsert2(
null,
null,
MetaTable.HOOKS,
insertObj
);
insertObj,
)
await NocoCache.appendToList(
CacheScope.HOOK,
[hook.fk_model_id],
`${CacheScope.HOOK}:${id}`
);
`${CacheScope.HOOK}:${id}`,
)
return this.get(id, ncMeta);
return this.get(id, ncMeta)
}
public static async update(
hookId: string,
hook: Partial<Hook>,
ncMeta = Noco.ncMeta
ncMeta = Noco.ncMeta,
) {
const updateObj = extractProps(hook, [
'title',
@ -203,38 +201,38 @@ export default class Hook implements HookType {
'retry_interval',
'timeout',
'active',
]);
])
if (updateObj.event) {
updateObj.event = updateObj.event.toLowerCase() as 'after' | 'before';
updateObj.event = updateObj.event.toLowerCase() as 'after' | 'before'
}
if (updateObj.operation) {
updateObj.operation = updateObj.operation.toLowerCase() as
| 'insert'
| 'delete'
| 'update';
| 'update'
}
if (updateObj.notification && typeof updateObj.notification === 'object') {
updateObj.notification = JSON.stringify(updateObj.notification);
updateObj.notification = JSON.stringify(updateObj.notification)
}
// get existing cache
const key = `${CacheScope.HOOK}:${hookId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const key = `${CacheScope.HOOK}:${hookId}`
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (o) {
// update data
o = { ...o, ...updateObj };
o = { ...o, ...updateObj }
// replace notification
o.notification = updateObj.notification;
o.notification = updateObj.notification
// set cache
await NocoCache.set(key, o);
await NocoCache.set(key, o)
}
// set meta
await ncMeta.metaUpdate(null, null, MetaTable.HOOKS, updateObj, hookId);
await ncMeta.metaUpdate(null, null, MetaTable.HOOKS, updateObj, hookId)
return this.get(hookId, ncMeta);
return this.get(hookId, ncMeta)
}
static async delete(hookId: any, ncMeta = Noco.ncMeta) {
@ -245,22 +243,22 @@ export default class Hook implements HookType {
MetaTable.FILTER_EXP,
{
condition: { fk_hook_id: hookId },
}
);
},
)
for (const filter of filterList) {
await NocoCache.deepDel(
CacheScope.FILTER_EXP,
`${CacheScope.FILTER_EXP}:${filter.id}`,
CacheDelDirection.CHILD_TO_PARENT
);
await HookFilter.delete(filter.id);
CacheDelDirection.CHILD_TO_PARENT,
)
await HookFilter.delete(filter.id)
}
// Delete Hook
await NocoCache.deepDel(
CacheScope.HOOK,
`${CacheScope.HOOK}:${hookId}`,
CacheDelDirection.CHILD_TO_PARENT
);
return await ncMeta.metaDelete(null, null, MetaTable.HOOKS, hookId);
CacheDelDirection.CHILD_TO_PARENT,
)
return await ncMeta.metaDelete(null, null, MetaTable.HOOKS, hookId)
}
}

8
packages/nocodb/src/lib/models/KanbanView.ts

@ -1,5 +1,5 @@
import Noco from '../Noco';
import { KanbanType, UITypes } from 'nocodb-sdk';
import { BoolType, KanbanType, UITypes } from 'nocodb-sdk';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View';
import NocoCache from '../cache/NocoCache';
@ -16,12 +16,12 @@ export default class KanbanView implements KanbanType {
// below fields are not in use at this moment
// keep them for time being
show?: boolean;
show?: BoolType;
order?: number;
uuid?: string;
public?: boolean;
public?: BoolType;
password?: string;
show_all_fields?: boolean;
show_all_fields?: BoolType;
constructor(data: KanbanView) {
Object.assign(this, data);

577
packages/nocodb/src/lib/models/Model.ts

File diff suppressed because it is too large Load Diff

2
packages/nocodb/src/lib/models/Project.ts

@ -1,6 +1,6 @@
import Base from './/Base';
import Noco from '../Noco';
import { BoolType, MetaType, ProjectType } from 'nocodb-sdk'
import { BoolType, MetaType, ProjectType } from 'nocodb-sdk';
import {
CacheDelDirection,
CacheGetType,

6
packages/nocodb/src/lib/services/apiTokenService.ts

@ -1,5 +1,5 @@
import { ApiTokenReqType, OrgUserRoles } from 'nocodb-sdk';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { NcError } from '../meta/helpers/catchError';
import ApiToken from '../models/ApiToken';
import User from '../models/User';
@ -11,7 +11,7 @@ export async function apiTokenCreate(param: {
userId: string;
tokenBody: ApiTokenReqType;
}) {
Tele.emit('evt', { evt_type: 'apiToken:created' });
T.emit('evt', { evt_type: 'apiToken:created' });
return ApiToken.insert({ ...param.tokenBody, fk_user_id: param.userId });
}
@ -23,7 +23,7 @@ export async function apiTokenDelete(param: { token; user: User }) {
) {
NcError.notFound('Token not found');
}
Tele.emit('evt', { evt_type: 'apiToken:deleted' });
T.emit('evt', { evt_type: 'apiToken:deleted' });
// todo: verify token belongs to the user
return await ApiToken.delete(param.token);

6
packages/nocodb/src/lib/services/attachmentService.ts

@ -4,7 +4,7 @@ import { nanoid } from 'nanoid';
import path from 'path';
import slash from 'slash';
import mimetypes, { mimeIcons } from '../utils/mimeTypes';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import NcPluginMgrv2 from '../meta/helpers/NcPluginMgrv2';
import Local from '../v1-legacy/plugins/adapters/storage/Local';
@ -47,7 +47,7 @@ export async function upload(param: {
})
);
Tele.emit('evt', { evt_type: 'image:uploaded' });
T.emit('evt', { evt_type: 'image:uploaded' });
return attachments;
}
@ -97,7 +97,7 @@ export async function uploadViaURL(param: {
})
);
Tele.emit('evt', { evt_type: 'image:uploaded' });
T.emit('evt', { evt_type: 'image:uploaded' });
return attachments;
}

10
packages/nocodb/src/lib/services/baseService.ts

@ -2,7 +2,7 @@ import Project from '../models/Project';
import { BaseReqType } from 'nocodb-sdk';
import { syncBaseMigration } from '../meta/helpers/syncMigration';
import Base from '../models/Base';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { populateMeta } from '../meta/api/helpers';
export async function baseGetWithConfig(param: { baseId: any }) {
@ -29,7 +29,7 @@ export async function baseUpdate(param: {
delete base.config;
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'base:updated',
});
@ -45,7 +45,7 @@ export async function baseList(param: { projectId: string }) {
export async function baseDelete(param: { baseId: string }) {
const base = await Base.get(param.baseId);
await base.delete();
Tele.emit('evt', { evt_type: 'base:deleted' });
T.emit('evt', { evt_type: 'base:deleted' });
return true;
}
@ -66,11 +66,11 @@ export async function baseCreate(param: {
const info = await populateMeta(base, project);
Tele.emit('evt_api_created', info);
T.emit('evt_api_created', info);
delete base.config;
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'base:created',
});

6
packages/nocodb/src/lib/services/cacheService.ts

@ -1,10 +1,10 @@
import NocoCache from '../cache/NocoCache';
export async function cacheGet() {
return await NocoCache.export();
return await NocoCache.export();
}
export async function cacheDelete() {
await NocoCache.destroy()
return true
await NocoCache.destroy();
return true;
}

50
packages/nocodb/src/lib/services/columnService.ts

@ -6,20 +6,21 @@ import {
LinkToAnotherColumnReqType,
LinkToAnotherRecordType,
RelationTypes,
substituteColumnAliasWithIdInFormula, substituteColumnIdWithAliasInFormula,
substituteColumnAliasWithIdInFormula,
substituteColumnIdWithAliasInFormula,
UITypes,
} from 'nocodb-sdk'
} from 'nocodb-sdk';
import formulaQueryBuilderv2 from '../db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2';
import ProjectMgrv2 from '../db/sql-mgr/v2/ProjectMgrv2';
import SqlMgrv2 from '../db/sql-mgr/v2/SqlMgrv2';
import { Altered } from '../meta/api/columnApis';
import {
createHmAndBtColumn,
generateFkName,
randomID,
validateLookupPayload, validateRequiredField,
validateLookupPayload,
validateRequiredField,
validateRollupPayload,
} from '../meta/api/helpers'
} from '../meta/api/helpers';
import { NcError } from '../meta/helpers/catchError';
import getColumnPropsFromUIDT from '../meta/helpers/getColumnPropsFromUIDT';
import {
@ -32,7 +33,7 @@ import NcMetaIO from '../meta/NcMetaIO';
import Audit from '../models/Audit';
import Base from '../models/Base';
import Column from '../models/Column';
import FormulaColumn from '../models/FormulaColumn'
import FormulaColumn from '../models/FormulaColumn';
import KanbanView from '../models/KanbanView';
import LinkToAnotherRecordColumn from '../models/LinkToAnotherRecordColumn';
import Model from '../models/Model';
@ -40,14 +41,21 @@ import Project from '../models/Project';
import Noco from '../Noco';
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import { Tele } from 'nc-help';
import { MetaTable } from '../utils/globals'
import { T } from 'nc-help';
import { MetaTable } from '../utils/globals';
export enum Altered {
NEW_COLUMN = 1,
DELETE_COLUMN = 4,
UPDATE_COLUMN = 8,
}
export async function columnUpdate(param: {
columnId: string;
column: ColumnReqType & {colOptions?: any},
cookie?: any,
column: ColumnReqType & { colOptions?: any };
cookie?: any;
}) {
const { cookie } = param;
const column = await Column.get({ colId: param.columnId });
const table = await Model.getWithInfo({
@ -88,7 +96,10 @@ export async function columnUpdate(param: {
NcError.badRequest('Duplicate column alias');
}
let colBody = { ...param.column } as Column & { formula?: string; formula_raw?: string };
let colBody = { ...param.column } as Column & {
formula?: string;
formula_raw?: string;
};
if (
[
UITypes.Lookup,
@ -606,7 +617,7 @@ export async function columnUpdate(param: {
await baseModel.bulkUpdateAll(
{ where: `(${column.title},eq,${ch.temp_title})` },
{ [column.column_name]: newOp.title },
{ cookie: req }
{ cookie }
);
}
} else if (column.uidt === UITypes.MultiSelect) {
@ -806,9 +817,9 @@ export async function columnUpdate(param: {
}).then(() => {});
await table.getColumns();
Tele.emit('evt', { evt_type: 'column:updated' });
T.emit('evt', { evt_type: 'column:updated' });
return table
return table;
}
export async function columnGet(param: { columnId: string }) {
@ -893,7 +904,7 @@ export async function columnAdd(param: {
case UITypes.LinkToAnotherRecord:
await createLTARColumn({ ...param, base, project });
Tele.emit('evt', { evt_type: 'relation:created' });
T.emit('evt', { evt_type: 'relation:created' });
break;
case UITypes.QrCode:
@ -1098,10 +1109,9 @@ export async function columnAdd(param: {
// ip: (req as any).clientIp,
}).then(() => {});
Tele.emit('evt', { evt_type: 'column:created' });
return table
T.emit('evt', { evt_type: 'column:created' });
return table;
}
export async function columnDelete(param: { columnId: string }) {
@ -1255,7 +1265,7 @@ export async function columnDelete(param: { columnId: string }) {
break;
}
}
Tele.emit('evt', { evt_type: 'raltion:deleted' });
T.emit('evt', { evt_type: 'raltion:deleted' });
break;
case UITypes.ForeignKey: {
NcError.notImplemented();
@ -1321,7 +1331,7 @@ export async function columnDelete(param: { columnId: string }) {
);
}
Tele.emit('evt', { evt_type: 'column:deleted' });
T.emit('evt', { evt_type: 'column:deleted' });
return table;
}

30
packages/nocodb/src/lib/services/dataService/export.ts

@ -1,25 +1,35 @@
import { Request, Response, Router } from 'express';
import { isSystemColumn } from 'nocodb-sdk'
import { isSystemColumn } from 'nocodb-sdk';
import * as XLSX from 'xlsx';
import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst'
import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import { extractXlsxData, serializeCellValue } from '../../meta/api/dataApis/helpers'
import {
extractCsvData, getViewAndModelByAliasOrId,
getViewAndModelFromRequestByAliasOrId, PathParams,
} from './helpers'
extractXlsxData,
serializeCellValue,
} from '../../meta/api/dataApis/helpers';
import {
extractCsvData,
getViewAndModelByAliasOrId,
getViewAndModelFromRequestByAliasOrId,
PathParams,
} from './helpers';
import apiMetrics from '../../helpers/apiMetrics';
import View from '../../../models/View';
async function excelDataExport(param:PathParams&{
query: any;
}) {
async function excelDataExport(
param: PathParams & {
query: any;
}
) {
const { model, view } = await getViewAndModelByAliasOrId(param);
let targetView = view;
if (!targetView) {
targetView = await View.getDefaultView(model.id);
}
const { offset, elapsed, data } = await extractXlsxData({view: targetView, query:req.query });
const { offset, elapsed, data } = await extractXlsxData({
view: targetView,
query: req.query,
});
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, data, targetView.title);
const buf = XLSX.write(wb, { type: 'base64', bookType: 'xlsx' });

172
packages/nocodb/src/lib/services/dataService/helpers.ts

@ -1,18 +1,18 @@
import { Request } from 'express'
import { nocoExecute } from 'nc-help'
import { isSystemColumn, UITypes } from 'nocodb-sdk'
import * as XLSX from 'xlsx'
import { BaseModelSqlv2 } from '../../db/sql-data-mapper/lib/sql/BaseModelSqlv2'
import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst'
import { NcError } from '../../meta/helpers/catchError'
import { Model, View } from '../../models'
import Base from '../../models/Base'
import Column from '../../models/Column'
import LinkToAnotherRecordColumn from '../../models/LinkToAnotherRecordColumn'
import LookupColumn from '../../models/LookupColumn'
import Project from '../../models/Project'
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2'
import { Request } from 'express';
import { nocoExecute } from 'nc-help';
import { isSystemColumn, UITypes } from 'nocodb-sdk';
import * as XLSX from 'xlsx';
import { BaseModelSqlv2 } from '../../db/sql-data-mapper/lib/sql/BaseModelSqlv2';
import getAst from '../../db/sql-data-mapper/lib/sql/helpers/getAst';
import { NcError } from '../../meta/helpers/catchError';
import { Model, View } from '../../models';
import Base from '../../models/Base';
import Column from '../../models/Column';
import LinkToAnotherRecordColumn from '../../models/LinkToAnotherRecordColumn';
import LookupColumn from '../../models/LookupColumn';
import Project from '../../models/Project';
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2';
import papaparse from 'papaparse';
export interface PathParams {
projectName: string;
@ -41,8 +41,6 @@ export async function getViewAndModelByAliasOrId(param: {
return { model, view };
}
export async function extractXlsxData(view: View, req: Request) {
const base = await Base.get(view.base_id);
@ -63,7 +61,12 @@ export async function extractXlsxData(view: View, req: Request) {
dbDriver: NcConnectionMgrv2.get(base),
});
const { offset, dbRows, elapsed } = await getDbRows(baseModel, view, req);
const { offset, dbRows, elapsed } = await getDbRows({
baseModel,
view,
siteUrl: (req as any).ncSiteUrl,
query: req.query,
});
const fields = req.query.fields as string[];
@ -93,7 +96,12 @@ export async function extractCsvData(view: View, req: Request) {
dbDriver: NcConnectionMgrv2.get(base),
});
const { offset, dbRows, elapsed } = await getDbRows(baseModel, view, req);
const { offset, dbRows, elapsed } = await getDbRows({
baseModel,
view,
query: req.query,
siteUrl: (req as any).ncSiteUrl,
});
const data = papaparse.unparse(
{
@ -118,70 +126,11 @@ export async function extractCsvData(view: View, req: Request) {
return { offset, dbRows, elapsed, data };
}
async function getDbRows(baseModel, view: View, req: Request) {
let offset = +req.query.offset || 0;
const limit = 100;
// const size = +process.env.NC_EXPORT_MAX_SIZE || 1024;
const timeout = +process.env.NC_EXPORT_MAX_TIMEOUT || 5000;
const dbRows = [];
const startTime = process.hrtime();
let elapsed, temp;
const listArgs: any = { ...req.query };
try {
listArgs.filterArr = JSON.parse(listArgs.filterArrJson);
} catch (e) {}
try {
listArgs.sortArr = JSON.parse(listArgs.sortArrJson);
} catch (e) {}
for (
elapsed = 0;
elapsed < timeout;
offset += limit,
temp = process.hrtime(startTime),
elapsed = temp[0] * 1000 + temp[1] / 1000000
) {
const rows = await nocoExecute(
await getAst({
query: req.query,
includePkByDefault: false,
model: view.model,
view,
}),
await baseModel.list({ ...listArgs, offset, limit }),
{},
req.query
);
if (!rows?.length) {
offset = -1;
break;
}
for (const row of rows) {
const dbRow = { ...row };
for (const column of view.model.columns) {
if (isSystemColumn(column) && !view.show_system_fields) continue;
dbRow[column.title] = await serializeCellValue({
value: row[column.title],
column,
siteUrl: req['ncSiteUrl'],
});
}
dbRows.push(dbRow);
}
}
return { offset, dbRows, elapsed };
}
export async function serializeCellValue({
value,
column,
siteUrl,
}: {
value,
column,
siteUrl,
}: {
column?: Column;
value: any;
siteUrl: string;
@ -209,34 +158,34 @@ export async function serializeCellValue({
);
}
case UITypes.Lookup:
{
const colOptions = await column.getColOptions<LookupColumn>();
const lookupColumn = await colOptions.getLookupColumn();
return (
await Promise.all(
[...(Array.isArray(value) ? value : [value])].map(async (v) =>
serializeCellValue({
value: v,
column: lookupColumn,
siteUrl,
})
{
const colOptions = await column.getColOptions<LookupColumn>();
const lookupColumn = await colOptions.getLookupColumn();
return (
await Promise.all(
[...(Array.isArray(value) ? value : [value])].map(async (v) =>
serializeCellValue({
value: v,
column: lookupColumn,
siteUrl,
})
)
)
)
).join(', ');
}
).join(', ');
}
break;
case UITypes.LinkToAnotherRecord:
{
const colOptions =
await column.getColOptions<LinkToAnotherRecordColumn>();
const relatedModel = await colOptions.getRelatedTable();
await relatedModel.getColumns();
return [...(Array.isArray(value) ? value : [value])]
.map((v) => {
return v[relatedModel.displayValue?.title];
})
.join(', ');
}
{
const colOptions =
await column.getColOptions<LinkToAnotherRecordColumn>();
const relatedModel = await colOptions.getRelatedTable();
await relatedModel.getColumns();
return [...(Array.isArray(value) ? value : [value])]
.map((v) => {
return v[relatedModel.displayValue?.title];
})
.join(', ');
}
break;
default:
if (value && typeof value === 'object') {
@ -263,9 +212,12 @@ export async function getColumnByIdOrName(
return column;
}
async function getDbRows(param: { baseModel:BaseModelSqlv2, view: View, query: any; siteUrl: string; }) {
export async function getDbRows(param: {
baseModel: BaseModelSqlv2;
view: View;
query: any;
siteUrl: string;
}) {
const { baseModel, view, query = {}, siteUrl } = param;
let offset = +query.offset || 0;
const limit = 100;

5
packages/nocodb/src/lib/services/dataService/index.ts

@ -4,7 +4,7 @@ import { NcError } from '../../meta/helpers/catchError';
import { PagedResponseImpl } from '../../meta/helpers/PagedResponse';
import { Base, Model, View } from '../../models';
import NcConnectionMgrv2 from '../../utils/common/NcConnectionMgrv2';
import { getViewAndModelByAliasOrId, PathParams } from './helpers'
import { getViewAndModelByAliasOrId, PathParams } from './helpers';
export async function dataList(param: PathParams & { query: any }) {
const { model, view } = await getViewAndModelByAliasOrId(param);
@ -322,7 +322,6 @@ export async function getGroupedDataList(param: {
return data;
}
export async function dataListByViewId(param: { viewId: string; query: any }) {
const view = await View.get(param.viewId);
@ -795,3 +794,5 @@ export async function relationDataAdd(param: {
return true;
}
export * from './helpers'

57
packages/nocodb/src/lib/services/filterService.ts

@ -1,68 +1,67 @@
import { FilterReqType } from 'nocodb-sdk'
import Filter from '../models/Filter'
import { Tele } from 'nc-help';
import { FilterReqType } from 'nocodb-sdk';
import Filter from '../models/Filter';
import { T } from 'nc-help';
export async function hookFilterCreate(param: { filter: FilterReqType; hookId: any }) {
export async function hookFilterCreate(param: {
filter: FilterReqType;
hookId: any;
}) {
const filter = await Filter.insert({
...param.filter,
fk_hook_id: param.hookId,
})
});
Tele.emit('evt', { evt_type: 'hookFilter:created' })
return filter
T.emit('evt', { evt_type: 'hookFilter:created' });
return filter;
}
export async function hookFilterList(param: { hookId: any }) {
return Filter.rootFilterListByHook({ hookId: param.hookId })
return Filter.rootFilterListByHook({ hookId: param.hookId });
}
export async function filterDelete(param: { filterId: string }) {
await Filter.delete(param.filterId)
Tele.emit('evt', { evt_type: 'filter:deleted' })
await Filter.delete(param.filterId);
T.emit('evt', { evt_type: 'filter:deleted' });
return true;
}
export async function filterCreate(param: {
filter: FilterReqType
viewId: string
filter: FilterReqType;
viewId: string;
}) {
const filter = await Filter.insert({
...param.filter,
fk_view_id: param.viewId,
});
Tele.emit('evt', { evt_type: 'filter:created' });
T.emit('evt', { evt_type: 'filter:created' });
return filter
return filter;
}
export async function filterUpdate(param: {
filter: FilterReqType
filterId: string
filter: FilterReqType;
filterId: string;
}) {
const filter = await Filter.update(param.filterId, param.filter)
// todo: type correction
const filter = await Filter.update(param.filterId, param.filter as Filter);
T.emit('evt', { evt_type: 'filter:updated' });
Tele.emit('evt', { evt_type: 'filter:updated' })
return filter
return filter;
}
export async function filterChildrenList(param: { filterId: any }) {
return Filter.parentFilterList({
parentId: param.filterId,
})
});
}
export async function filterGet(param: { filterId: string }) {
const filter = await Filter.get(param.filterId)
return filter
const filter = await Filter.get(param.filterId);
return filter;
}
export async function filterList(param: { viewId: string }) {
const filter = await Filter.rootFilterList({ viewId: param.viewId })
return filter
const filter = await Filter.rootFilterList({ viewId: param.viewId });
return filter;
}

4
packages/nocodb/src/lib/services/formViewColumnService.ts

@ -1,11 +1,11 @@
import { FormViewColumn } from '../models';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function columnUpdate(param: {
formViewColumnId: string;
// todo: replace with FormColumnReq
formViewColumn: FormViewColumn;
}) {
Tele.emit('evt', { evt_type: 'formViewColumn:updated' });
T.emit('evt', { evt_type: 'formViewColumn:updated' });
return await FormViewColumn.update(
param.formViewColumnId,
param.formViewColumn

6
packages/nocodb/src/lib/services/formViewService.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { FormReqType, ViewTypes } from 'nocodb-sdk';
import { FormView, View } from '../models';
@ -11,7 +11,7 @@ export async function formViewCreate(param: {
tableId: string;
body: FormReqType;
}) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'form' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'form' });
const view = await View.insert({
...param.body,
// todo: sanitize
@ -26,6 +26,6 @@ export async function formViewUpdate(param: {
formViewId: string;
body: FormReqType;
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'grid' });
T.emit('evt', { evt_type: 'view:updated', type: 'grid' });
await FormView.update(param.formViewId, param.body);
}

8
packages/nocodb/src/lib/services/galleryViewService.ts

@ -1,6 +1,6 @@
import { GalleryReqType, ViewTypes } from 'nocodb-sdk';
import { Tele } from 'nc-help';
import { GalleryView, View } from '../models'
import { T } from 'nc-help';
import { GalleryView, View } from '../models';
export async function galleryViewGet(param: { galleryViewId: string }) {
return await GalleryView.get(param.galleryViewId);
@ -10,7 +10,7 @@ export async function galleryViewCreate(param: {
tableId: string;
gallery: GalleryReqType;
}) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'gallery' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'gallery' });
const view = await View.insert({
...param.gallery,
// todo: sanitize
@ -24,6 +24,6 @@ export async function galleryViewUpdate(param: {
galleryViewId: string;
gallery: GalleryReqType;
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'gallery' });
T.emit('evt', { evt_type: 'view:updated', type: 'gallery' });
await GalleryView.update(param.galleryViewId, param.gallery);
}

4
packages/nocodb/src/lib/services/gridViewColumnService.ts

@ -1,6 +1,6 @@
import { GridColumnReqType } from 'nocodb-sdk';
import GridViewColumn from '../models/GridViewColumn';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function columnList(param: { gridViewId: string }) {
return await GridViewColumn.list(param.gridViewId);
@ -10,6 +10,6 @@ export async function gridColumnUpdate(param: {
gridViewColumnId: string;
grid: GridColumnReqType;
}) {
Tele.emit('evt', { evt_type: 'gridViewColumn:updated' });
T.emit('evt', { evt_type: 'gridViewColumn:updated' });
return await GridViewColumn.update(param.gridViewColumnId, param.grid);
}

6
packages/nocodb/src/lib/services/gridViewService.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { GridReqType, ViewTypes } from 'nocodb-sdk';
import { View } from '../models';
import { GridView } from '../models';
@ -13,7 +13,7 @@ export async function gridViewCreate(param: {
fk_model_id: param.tableId,
type: ViewTypes.GRID,
});
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'grid' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'grid' });
return view;
}
@ -21,6 +21,6 @@ export async function gridViewUpdate(param: {
viewId: string;
grid: GridReqType;
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'grid' });
T.emit('evt', { evt_type: 'view:updated', type: 'grid' });
return await GridView.update(param.viewId, param.grid);
}

8
packages/nocodb/src/lib/services/hookFilterService.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { FilterReqType } from 'nocodb-sdk';
import Filter from '../models/Filter';
@ -37,7 +37,7 @@ export async function filterCreate(param: {
fk_hook_id: param.hookId,
});
Tele.emit('evt', { evt_type: 'hookFilter:created' });
T.emit('evt', { evt_type: 'hookFilter:created' });
return filter;
}
@ -50,12 +50,12 @@ export async function filterUpdate(param: {
...param.filter,
fk_hook_id: param.hookId,
} as Filter);
Tele.emit('evt', { evt_type: 'hookFilter:updated' });
T.emit('evt', { evt_type: 'hookFilter:updated' });
return filter;
}
export async function filterDelete(param: { filterId: string }) {
await Filter.delete(param.filterId);
Tele.emit('evt', { evt_type: 'hookFilter:deleted' });
T.emit('evt', { evt_type: 'hookFilter:deleted' });
return true;
}

16
packages/nocodb/src/lib/services/hookService.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { Hook, Model } from '../models';
import { HookReqType, HookTestReqType } from 'nocodb-sdk';
@ -14,24 +14,26 @@ export async function hookCreate(param: {
tableId: string;
hook: HookReqType;
}) {
Tele.emit('evt', { evt_type: 'webhooks:created' });
T.emit('evt', { evt_type: 'webhooks:created' });
// todo: type correction
const hook = await Hook.insert({
...param.hook,
fk_model_id: param.tableId,
});
} as any);
return hook;
}
export async function hookDelete(param: { hookId: string }) {
Tele.emit('evt', { evt_type: 'webhooks:deleted' });
T.emit('evt', { evt_type: 'webhooks:deleted' });
await Hook.delete(param.hookId);
return true;
}
export async function hookUpdate(param: { hookId: string; hook: HookReqType }) {
Tele.emit('evt', { evt_type: 'webhooks:updated' });
T.emit('evt', { evt_type: 'webhooks:updated' });
return await Hook.update(param.hookId, param.hook);
// todo: correction in swagger
return await Hook.update(param.hookId, param.hook as any);
}
export async function hookTest(param: {
@ -53,7 +55,7 @@ export async function hookTest(param: {
true
);
Tele.emit('evt', { evt_type: 'webhooks:tested' });
T.emit('evt', { evt_type: 'webhooks:tested' });
return true;
}

6
packages/nocodb/src/lib/services/kanbanViewService.ts

@ -1,6 +1,6 @@
import { KanbanReqType, ViewTypes } from 'nocodb-sdk';
import { KanbanView, View } from '../models';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function kanbanViewGet(param: { kanbanViewId: string }) {
return await KanbanView.get(param.kanbanViewId);
@ -10,7 +10,7 @@ export async function kanbanViewCreate(param: {
tableId: string;
kanban: KanbanReqType;
}) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'kanban' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'kanban' });
const view = await View.insert({
...param.kanban,
// todo: sanitize
@ -24,6 +24,6 @@ export async function kanbanViewUpdate(param: {
kanbanViewId: string;
kanban: KanbanReqType;
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'kanban' });
T.emit('evt', { evt_type: 'view:updated', type: 'kanban' });
return await KanbanView.update(param.kanbanViewId, param.kanban);
}

25
packages/nocodb/src/lib/services/mapViewService.ts

@ -1,18 +1,18 @@
import { MapType, ViewTypes } from 'nocodb-sdk';
import View from '../models/View';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import MapView from '../models/MapView';
export async function mapViewGet(param:{mapViewId: string}) {
return await MapView.get(param.mapViewId)
export async function mapViewGet(param: { mapViewId: string }) {
return await MapView.get(param.mapViewId);
}
export async function mapViewCreate(param:{
tableId: string,
export async function mapViewCreate(param: {
tableId: string;
// todo: add MapReq in schema
map: MapType
map: MapType;
}) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'map' });
T.emit('evt', { evt_type: 'vtable:created', show_as: 'map' });
const view = await View.insert({
...param.map,
// todo: sanitize
@ -22,13 +22,12 @@ export async function mapViewCreate(param:{
return view;
}
export async function mapViewUpdate(param:{
mapViewId: string,
export async function mapViewUpdate(param: {
mapViewId: string;
// todo: add MapReq in schema
map: MapType
map: MapType;
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'map' });
T.emit('evt', { evt_type: 'view:updated', type: 'map' });
// todo: type correction
return await MapView.update(param.mapViewId, param.map as any)
return await MapView.update(param.mapViewId, param.map as any);
}

10
packages/nocodb/src/lib/services/metaDiffService.ts

@ -1,6 +1,6 @@
// // Project CRUD
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import { isVirtualCol, ModelTypes, RelationTypes, UITypes } from 'nocodb-sdk';
import {
@ -576,9 +576,7 @@ export async function baseMetaDiff(param: {
return changes;
}
export async function metaDiffSync(param: {
projectId: string;
}) {
export async function metaDiffSync(param: { projectId: string }) {
const project = await Project.getWithInfo(param.projectId);
for (const base of project.bases) {
const virtualColumnInsert: Array<() => Promise<void>> = [];
@ -777,7 +775,7 @@ export async function metaDiffSync(param: {
await extractAndGenerateManyToManyRelations(await base.getModels());
}
Tele.emit('evt', { evt_type: 'metaDiff:synced' });
T.emit('evt', { evt_type: 'metaDiff:synced' });
return true;
}
@ -969,7 +967,7 @@ export async function baseMetaDiffSync(param: {
// populate m2m relations
await extractAndGenerateManyToManyRelations(await base.getModels());
Tele.emit('evt', { evt_type: 'baseMetaDiff:synced' });
T.emit('evt', { evt_type: 'baseMetaDiff:synced' });
return true;
}

6
packages/nocodb/src/lib/services/modelVisibilityService.ts

@ -2,13 +2,13 @@ import { VisibilityRuleReqType } from 'nocodb-sdk';
import { NcError } from '../meta/helpers/catchError';
import Model from '../models/Model';
import ModelRoleVisibility from '../models/ModelRoleVisibility';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function xcVisibilityMetaSetAll(param: {
visibilityRule: VisibilityRuleReqType;
projectId: string;
}) {
Tele.emit('evt', { evt_type: 'uiAcl:updated' });
T.emit('evt', { evt_type: 'uiAcl:updated' });
for (const d of param.visibilityRule) {
for (const role of Object.keys(d.disabled)) {
const view = await Model.get(d.id);
@ -40,7 +40,7 @@ export async function xcVisibilityMetaSetAll(param: {
}
}
}
Tele.emit('evt', { evt_type: 'uiAcl:updated' });
T.emit('evt', { evt_type: 'uiAcl:updated' });
return true;
}

8
packages/nocodb/src/lib/services/orgLicenseService.ts

@ -5,13 +5,11 @@ import Noco from '../Noco';
export async function licenseGet() {
const license = await Store.get(NC_LICENSE_KEY);
return { key: license?.value }
return { key: license?.value };
}
export async function licenseSet(param:{
key: string
}) {
export async function licenseSet(param: { key: string }) {
await Store.saveOrUpdate({ value: param.key, key: NC_LICENSE_KEY });
await Noco.loadEEState();
return true
return true;
}

6
packages/nocodb/src/lib/services/orgTokenService.ts

@ -1,7 +1,7 @@
import { ApiTokenReqType, OrgUserRoles } from 'nocodb-sdk';
import { User } from '../models';
import ApiToken from '../models/ApiToken';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { NcError } from '../meta/helpers/catchError';
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
@ -32,7 +32,7 @@ export async function apiTokenCreate(param: {
user: User;
apiToken: ApiTokenReqType;
}) {
Tele.emit('evt', { evt_type: 'org:apiToken:created' });
T.emit('evt', { evt_type: 'org:apiToken:created' });
return await ApiToken.insert({
...param.apiToken,
fk_user_id: param['user'].id,
@ -48,6 +48,6 @@ export async function apiTokenDelete(param: { user: User; token: string }) {
) {
NcError.notFound('Token not found');
}
Tele.emit('evt', { evt_type: 'org:apiToken:deleted' });
T.emit('evt', { evt_type: 'org:apiToken:deleted' });
return await ApiToken.delete(param.token);
}

4
packages/nocodb/src/lib/services/orgUserService.ts

@ -11,7 +11,7 @@ import { NC_APP_SETTINGS } from '../constants';
import { Audit, ProjectUser, Store, SyncSource, User } from '../models';
import Noco from '../Noco';
import { MetaTable } from '../utils/globals';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { NcError } from '../meta/helpers/catchError';
import { extractProps } from '../meta/helpers/extractProps';
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
@ -142,7 +142,7 @@ export async function userAdd(param: {
});
const count = await User.count();
Tele.emit('evt', { evt_type: 'org:user:invite', count });
T.emit('evt', { evt_type: 'org:user:invite', count });
await Audit.insert({
op_type: AuditOperationTypes.ORG_USER,

29
packages/nocodb/src/lib/services/pluginService.ts

@ -1,30 +1,31 @@
import { Tele } from 'nc-help';
import { Plugin } from '../models'
import { PluginTestReqType, PluginType } from 'nocodb-sdk'
import { T } from 'nc-help';
import { Plugin } from '../models';
import { PluginTestReqType, PluginType } from 'nocodb-sdk';
import NcPluginMgrv2 from '../meta/helpers/NcPluginMgrv2';
export async function pluginList() {
return await Plugin.list()
return await Plugin.list();
}
export async function pluginTest(param:{body: PluginTestReqType}) {
Tele.emit('evt', { evt_type: 'plugin:tested' });
return await NcPluginMgrv2.test(param.body)
export async function pluginTest(param: { body: PluginTestReqType }) {
T.emit('evt', { evt_type: 'plugin:tested' });
return await NcPluginMgrv2.test(param.body);
}
export async function pluginRead(param: { pluginId: string }) {
return await Plugin.get(param.pluginId)
return await Plugin.get(param.pluginId);
}
export async function pluginUpdate(
param: { pluginId: string; plugin: PluginType }
) {
export async function pluginUpdate(param: {
pluginId: string;
plugin: PluginType;
}) {
const plugin = await Plugin.update(param.pluginId, param.plugin);
Tele.emit('evt', {
T.emit('evt', {
evt_type: plugin.active ? 'plugin:installed' : 'plugin:uninstalled',
title: plugin.title,
});
return plugin
return plugin;
}
export async function isPluginActive(param: { pluginTitle: string }) {
return await Plugin.isPluginActive(param.pluginTitle)
return await Plugin.isPluginActive(param.pluginTitle);
}

14
packages/nocodb/src/lib/services/projectService.ts

@ -1,5 +1,5 @@
import DOMPurify from 'isomorphic-dompurify';
import { OrgUserRoles, ProjectReqType, } from 'nocodb-sdk';
import { OrgUserRoles, ProjectReqType } from 'nocodb-sdk';
import { promisify } from 'util';
import { populateMeta } from '../meta/api/helpers';
import { extractPropsAndSanitize } from '../meta/helpers/extractProps';
@ -95,23 +95,23 @@ export async function projectCreate(param: {
for (const base of await project.getBases()) {
const info = await populateMeta(base, project);
Tele.emit('evt_api_created', info);
T.emit('evt_api_created', info);
delete base.config;
}
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:created',
xcdb: !projectBody.external,
});
Tele.emit('evt', { evt_type: 'project:rest' });
T.emit('evt', { evt_type: 'project:rest' });
project;
}
const nanoid = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 4);
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function getProjectWithInfo(param: { projectId: string }) {
const project = await Project.getWithInfo(param.projectId);
@ -120,7 +120,7 @@ export async function getProjectWithInfo(param: { projectId: string }) {
export async function projectSoftDelete(param: { projectId: any }) {
await Project.softDelete(param.projectId);
Tele.emit('evt', { evt_type: 'project:deleted' });
T.emit('evt', { evt_type: 'project:deleted' });
return true;
}
@ -152,7 +152,7 @@ export async function projectUpdate(param: {
}
const result = await Project.update(param.projectId, data);
Tele.emit('evt', { evt_type: 'project:update' });
T.emit('evt', { evt_type: 'project:update' });
return result;
}

4
packages/nocodb/src/lib/services/projectUserService.ts

@ -1,5 +1,5 @@
import { OrgUserRoles, ProjectUserReqType } from 'nocodb-sdk';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { PagedResponseImpl } from '../meta/helpers/PagedResponse';
import ProjectUser from '../models/ProjectUser';
import validator from 'validator';
@ -109,7 +109,7 @@ export async function userInvite(param: {
});
const count = await User.count();
Tele.emit('evt', { evt_type: 'project:invite', count });
T.emit('evt', { evt_type: 'project:invite', count });
await Audit.insert({
project_id: param.projectId,

17
packages/nocodb/src/lib/services/sharedBaseService.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { v4 as uuidv4 } from 'uuid';
import Project from '../models/Project';
import { NcError } from '../meta/helpers/catchError';
@ -7,7 +7,7 @@ const config = {
dashboardPath: '/nc',
};
export async function createSharedBaseLink(param:{
export async function createSharedBaseLink(param: {
projectId: string;
roles: string;
password: string;
@ -34,7 +34,7 @@ export async function createSharedBaseLink(param:{
data.url = `${param.siteUrl}${config.dashboardPath}#/nc/base/${data.uuid}`;
delete data.password;
Tele.emit('evt', { evt_type: 'sharedBase:generated-link' });
T.emit('evt', { evt_type: 'sharedBase:generated-link' });
return data;
}
@ -64,11 +64,11 @@ export async function updateSharedBaseLink(param: {
data.url = `${param.siteUrl}${config.dashboardPath}#/nc/base/${data.uuid}`;
delete data.password;
Tele.emit('evt', { evt_type: 'sharedBase:generated-link' });
T.emit('evt', { evt_type: 'sharedBase:generated-link' });
return data;
}
export async function disableSharedBaseLink(param:{
export async function disableSharedBaseLink(param: {
projectId: string;
}): Promise<any> {
const project = await Project.get(param.projectId);
@ -82,12 +82,12 @@ export async function disableSharedBaseLink(param:{
await Project.update(project.id, data);
Tele.emit('evt', { evt_type: 'sharedBase:disable-link' });
T.emit('evt', { evt_type: 'sharedBase:disable-link' });
return { uuid: null }
return { uuid: null };
}
export async function getSharedBaseLink(param:{
export async function getSharedBaseLink(param: {
projectId: string;
siteUrl: string;
}): Promise<any> {
@ -105,4 +105,3 @@ export async function getSharedBaseLink(param:{
return data;
}

9
packages/nocodb/src/lib/services/sortService.ts

@ -1,21 +1,20 @@
import { SortReqType } from 'nocodb-sdk';
import Sort from '../models/Sort';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export async function sortGet(param: { sortId: string }) {
return Sort.get(param.sortId);
}
export async function sortDelete(param: { sortId: string }) {
await Sort.delete(param.sortId);
Tele.emit('evt', { evt_type: 'sort:deleted' });
T.emit('evt', { evt_type: 'sort:deleted' });
return true;
}
export async function sortUpdate(param: { sortId: any; sort: SortReqType }) {
const sort = await Sort.update(param.sortId, param.sort);
Tele.emit('evt', { evt_type: 'sort:updated' });
T.emit('evt', { evt_type: 'sort:updated' });
return sort;
}
@ -24,7 +23,7 @@ export async function sortCreate(param: { viewId: any; sort: SortReqType }) {
...param.sort,
fk_view_id: param.viewId,
} as Sort);
Tele.emit('evt', { evt_type: 'sort:created' });
T.emit('evt', { evt_type: 'sort:created' });
return sort;
}

2
packages/nocodb/src/lib/services/swaggerService/getSwaggerJSON.ts

@ -1,4 +1,4 @@
import { Model, Project, View } from '../../models'
import { Model, Project, View } from '../../models';
import FormViewColumn from '../../models/FormViewColumn';
import GalleryViewColumn from '../../models/GalleryViewColumn';
import Noco from '../../Noco';

13
packages/nocodb/src/lib/services/swaggerService/index.ts

@ -1,9 +1,12 @@
import { NcError } from '../../meta/helpers/catchError'
import Model from '../../models/Model'
import Project from '../../models/Project'
import getSwaggerJSON from './getSwaggerJSON'
import { NcError } from '../../meta/helpers/catchError';
import Model from '../../models/Model';
import Project from '../../models/Project';
import getSwaggerJSON from './getSwaggerJSON';
export async function swaggerJson(param:{projectId:string; siteUrl:string}){
export async function swaggerJson(param: {
projectId: string;
siteUrl: string;
}) {
const project = await Project.get(param.projectId);
if (!project) NcError.notFound();

6
packages/nocodb/src/lib/services/syncService/helpers/job.ts

@ -1,4 +1,4 @@
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import FetchAT from './fetchAT';
import { UITypes } from 'nocodb-sdk';
// import * as sMap from './syncMap';
@ -1933,7 +1933,7 @@ export default async (
});
}
Tele.event({
T.event({
event: 'a:airtable-import:success',
data: {
stats: {
@ -2386,7 +2386,7 @@ export default async (
}
} catch (e) {
if (e.response?.data?.msg) {
Tele.event({
T.event({
event: 'a:airtable-import:error',
data: { error: e.response.data.msg },
});

18
packages/nocodb/src/lib/services/syncService/index.ts

@ -1,6 +1,6 @@
import { Tele } from 'nc-help';
import { PagedResponseImpl } from '../../meta/helpers/PagedResponse'
import { Project, SyncSource } from '../../models'
import { T } from 'nc-help';
import { PagedResponseImpl } from '../../meta/helpers/PagedResponse';
import { Project, SyncSource } from '../../models';
export async function syncSourceList(param: {
projectId: string;
@ -18,7 +18,7 @@ export async function syncCreate(param: {
// todo: define type
syncPayload: Partial<SyncSource>;
}) {
Tele.emit('evt', { evt_type: 'webhooks:created' });
T.emit('evt', { evt_type: 'webhooks:created' });
const project = await Project.getWithInfo(param.projectId);
const sync = await SyncSource.insert({
@ -31,17 +31,17 @@ export async function syncCreate(param: {
}
export async function syncDelete(param: { syncId: string }) {
Tele.emit('evt', { evt_type: 'webhooks:deleted' });
return await SyncSource.delete(param.syncId)
T.emit('evt', { evt_type: 'webhooks:deleted' });
return await SyncSource.delete(param.syncId);
}
export async function syncUpdate(param:{
export async function syncUpdate(param: {
syncId: string;
syncPayload: Partial<SyncSource>;
}) {
Tele.emit('evt', { evt_type: 'webhooks:updated' });
T.emit('evt', { evt_type: 'webhooks:updated' });
return await SyncSource.update(param.syncId, param.syncPayload)
return await SyncSource.update(param.syncId, param.syncPayload);
}
export { default as airtableImportJob } from './helpers/job';

9
packages/nocodb/src/lib/services/tableService.ts

@ -26,7 +26,7 @@ import Project from '../models/Project';
import User from '../models/User';
import View from '../models/View';
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
export function reorderTable(param: { tableId: string; order: any }) {
return Model.updateOrder(param.tableId, param.order);
@ -84,7 +84,7 @@ export async function tableDelete(param: { tableId: string; user: User }) {
// ip: (req as any).clientIp,
}).then(() => {});
Tele.emit('evt', { evt_type: 'table:deleted' });
T.emit('evt', { evt_type: 'table:deleted' });
return table.delete();
}
@ -319,8 +319,9 @@ export async function tableCreate(args: {
mapDefaultDisplayValue(args.table.columns);
Tele.emit('evt', { evt_type: 'table:created' });
T.emit('evt', { evt_type: 'table:created' });
// todo: type correction
const result = await Model.insert(project.id, base.id, {
...args.table,
columns: columns.map((c, i) => {
@ -342,7 +343,7 @@ export async function tableCreate(args: {
} as NormalColumnRequestType;
}),
order: +(tables?.pop()?.order ?? 0) + 1,
});
} as any);
return result;
}

4
packages/nocodb/src/lib/services/userService/helpers.ts

@ -1,7 +1,7 @@
import * as jwt from 'jsonwebtoken';
import crypto from 'crypto';
import { NcConfig } from '../../../interface/config'
import { User } from '../../models'
import { NcConfig } from '../../../interface/config';
import { User } from '../../models';
export function genJwt(user: User, config: NcConfig) {
return jwt.sign(

87
packages/nocodb/src/lib/services/userService/index.ts

@ -1,46 +1,35 @@
import { Request, Response } from 'express';
import {
PasswordChangeReqType,
PasswordForgotReqType, PasswordResetReqType,
SignUpReqType,
TableType,
PasswordForgotReqType,
PasswordResetReqType,
UserType,
validatePassword,
} from 'nocodb-sdk'
} from 'nocodb-sdk';
import { OrgUserRoles } from 'nocodb-sdk';
import { NC_APP_SETTINGS } from '../../../constants';
import Store from '../../../models/Store';
import { Tele } from 'nc-help';
import catchError, { NcError } from '../../helpers/catchError';
import { T } from 'nc-help';
const { isEmail } = require('validator');
import * as ejs from 'ejs';
import bcrypt from 'bcryptjs';
import { promisify } from 'util';
import User from '../../../models/User';
import { NC_APP_SETTINGS } from '../../constants';
import { NcError } from '../../meta/helpers/catchError';
import NcPluginMgrv2 from '../../meta/helpers/NcPluginMgrv2';
import { Audit, Store, User } from '../../models';
import Noco from '../../Noco';
import { MetaTable } from '../../utils/globals';
import { randomTokenString } from './helpers';
const { v4: uuidv4 } = require('uuid');
import Audit from '../../../models/Audit';
import NcPluginMgrv2 from '../../helpers/NcPluginMgrv2';
import passport from 'passport';
import extractProjectIdAndAuthenticate from '../../helpers/extractProjectIdAndAuthenticate';
import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import { MetaTable } from '../../../utils/globals';
import Noco from '../../../Noco';
import { getAjvValidatorMw } from '../helpers';
import { genJwt } from './helpers';
import { randomTokenString } from '../../helpers/stringHelpers';
export async function registerNewUserIfAllowed({
firstname,
lastname,
email,
salt,
password,
email_verification_token,
}: {
firstname,
lastname,
email,
salt,
password,
email_verification_token,
}: {
firstname;
lastname;
email: string;
@ -54,7 +43,7 @@ export async function registerNewUserIfAllowed({
roles = `${OrgUserRoles.CREATOR},${OrgUserRoles.SUPER_ADMIN}`;
// todo: update in nc_store
// roles = 'owner,creator,editor'
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
@ -85,11 +74,10 @@ export async function registerNewUserIfAllowed({
});
}
export async function passwordChange(param: {
body: PasswordChangeReqType
user: UserType
req:any
body: PasswordChangeReqType;
user: UserType;
req: any;
}): Promise<any> {
const { currentPassword, newPassword } = param.body;
@ -133,13 +121,13 @@ export async function passwordChange(param: {
ip: param.req?.clientIp,
});
return true
return true;
}
export async function passwordForgot(param:{
export async function passwordForgot(param: {
body: PasswordForgotReqType;
siteUrl: string;
req:any
req: any;
}): Promise<any> {
const _email = param.body.email;
@ -165,9 +153,7 @@ export async function passwordForgot(param:{
adapter.mailSend({
to: user.email,
subject: 'Password Reset Link',
text: `Visit following link to update your password : ${
param.siteUrl
}/auth/password/reset/${token}.`,
text: `Visit following link to update your password : ${param.siteUrl}/auth/password/reset/${token}.`,
html: ejs.render(template, {
resetLink: param.siteUrl + `/auth/password/reset/${token}`,
}),
@ -191,12 +177,10 @@ export async function passwordForgot(param:{
return NcError.badRequest('Your email has not been registered.');
}
return true
return true;
}
export async function tokenValidate(param:{
token: string;
}): Promise<any> {
export async function tokenValidate(param: { token: string }): Promise<any> {
const token = param.token;
const user = await Noco.ncMeta.metaGet(null, null, MetaTable.USERS, {
@ -210,14 +194,14 @@ export async function tokenValidate(param:{
NcError.badRequest('Password reset url expired');
}
return true
return true;
}
export async function passwordReset(param:{
export async function passwordReset(param: {
body: PasswordResetReqType;
token: string;
// todo: exclude
req:any;
req: any;
}): Promise<any> {
const { token, body, req } = param;
@ -261,7 +245,7 @@ export async function passwordReset(param:{
ip: req.clientIp,
});
return true
return true;
}
export async function emailVerification(param: {
@ -293,9 +277,8 @@ export async function emailVerification(param: {
ip: req.clientIp,
});
return true
return true;
}
export * from './helpers'
export * from './initAdminFromEnv'
export * from './helpers';
export { default as initAdminFromEnv } from './initAdminFromEnv';

15
packages/nocodb/src/lib/services/userService/initAdminFromEnv.ts

@ -1,15 +1,14 @@
import User from '../../../models/User';
import { v4 as uuidv4 } from 'uuid';
import { promisify } from 'util';
import bcrypt from 'bcryptjs';
import Noco from '../../../Noco';
import { CacheScope, MetaTable } from '../../../utils/globals';
import ProjectUser from '../../../models/ProjectUser';
import { validatePassword } from 'nocodb-sdk';
import boxen from 'boxen';
import NocoCache from '../../../cache/NocoCache';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import NocoCache from '../../cache/NocoCache';
import { ProjectUser, User } from '../../models';
import Noco from '../../Noco';
import { CacheScope, MetaTable } from '../../utils/globals';
const { isEmail } = require('validator');
const rolesLevel = { owner: 0, creator: 1, editor: 2, commenter: 3, viewer: 4 };
@ -68,7 +67,7 @@ export default async function initAdminFromEnv(_ncMeta = Noco.ncMeta) {
// if super admin not present
if (await User.isFirst(ncMeta)) {
// roles = 'owner,creator,editor'
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});
@ -126,7 +125,7 @@ export default async function initAdminFromEnv(_ncMeta = Noco.ncMeta) {
ncMeta
);
} else {
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'project:invite',
count: 1,
});

70
packages/nocodb/src/lib/services/userService/ui/auth/emailVerify.ts

@ -0,0 +1,70 @@
export default `<!DOCTYPE html>
<html>
<head>
<title>NocoDB - Verify Email</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link href="<%- ncPublicUrl %>/css/fonts.roboto.css" rel="stylesheet">
<link href="<%- ncPublicUrl %>/css/materialdesignicons.5.x.min.css" rel="stylesheet">
<link href="<%- ncPublicUrl %>/css/vuetify.2.x.min.css" rel="stylesheet">
<script src="<%- ncPublicUrl %>/js/vue.2.6.14.min.js"></script>
</head>
<body>
<div id="app">
<v-app>
<v-container>
<v-row class="justify-center">
<v-col class="col-12 col-md-6">
<v-alert v-if="valid" type="success">
Email verified successfully!
</v-alert>
<v-alert v-else-if="errMsg" type="error">
{{errMsg}}
</v-alert>
<template v-else>
<v-skeleton-loader type="heading"></v-skeleton-loader>
</template>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
<script src="<%- ncPublicUrl %>/js/vuetify.2.x.min.js"></script>
<script src="<%- ncPublicUrl %>/js/axios.0.19.2.min.js"></script>
<script>
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
valid: null,
errMsg: null,
validForm: false,
token: <%- token %>,
greeting: 'Password Reset',
formdata: {
password: '',
newPassword: ''
},
success: false
},
methods: {},
async created() {
try {
const valid = (await axios.post('<%- baseUrl %>/api/v1/auth/email/validate/' + this.token)).data;
this.valid = !!valid;
} catch (e) {
this.valid = false;
if(e.response && e.response.data && e.response.data.msg){
this.errMsg = e.response.data.msg;
}else{
this.errMsg = 'Some error occurred';
}
}
}
})
</script>
</body>
</html>`;

108
packages/nocodb/src/lib/services/userService/ui/auth/resetPassword.ts

@ -0,0 +1,108 @@
export default `<!DOCTYPE html>
<html>
<head>
<title>NocoDB - Reset Password</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link href="<%- ncPublicUrl %>/css/fonts.roboto.css" rel="stylesheet">
<link href="<%- ncPublicUrl %>/css/materialdesignicons.5.x.min.css" rel="stylesheet">
<link href="<%- ncPublicUrl %>/css/vuetify.2.x.min.css" rel="stylesheet">
<script src="<%- ncPublicUrl %>/js/vue.2.6.14.min.js"></script>
</head>
<body>
<div id="app">
<v-app>
<v-container>
<v-row class="justify-center">
<v-col class="col-12 col-md-6">
<v-alert v-if="success" type="success">
Password reset successful!
</v-alert>
<template v-else>
<v-form ref="form" v-model="validForm" v-if="valid === true" ref="formType" class="ma-auto"
lazy-validation>
<v-text-field
name="input-10-2"
label="New password"
type="password"
v-model="formdata.password"
:rules="[v => !!v || 'Password is required']"
></v-text-field>
<v-text-field
name="input-10-2"
type="password"
label="Confirm new password"
v-model="formdata.newPassword"
:rules="[v => !!v || 'Password is required', v => v === formdata.password || 'Password mismatch']"
></v-text-field>
<v-btn
:disabled="!validForm"
large
@click="resetPassword"
>
RESET PASSWORD
</v-btn>
</v-form>
<div v-else-if="valid === false">Not a valid url</div>
<div v-else>
<v-skeleton-loader type="actions"></v-skeleton-loader>
</div>
</template>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
<script src="<%- ncPublicUrl %>/js/vuetify.2.x.min.js"></script>
<script src="<%- ncPublicUrl %>/js/axios.0.19.2.min.js"></script>
<script>
var app = new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
valid: null,
validForm: false,
token: <%- token %>,
greeting: 'Password Reset',
formdata: {
password: '',
newPassword: ''
},
success: false
},
methods: {
async resetPassword() {
if (this.$refs.form.validate()) {
try {
const res = await axios.post('<%- baseUrl %>api/v1/db/auth/password/reset/' + this.token, {
...this.formdata
});
this.success = true;
} catch (e) {
if (e.response && e.response.data && e.response.data.msg) {
alert('Failed to reset password: ' + e.response.data.msg)
} else {
alert('Some error occurred')
}
}
}
}
},
async created() {
try {
const valid = (await axios.post('<%- baseUrl %>api/v1/db/auth/token/validate/' + this.token)).data;
this.valid = !!valid;
} catch (e) {
this.valid = false;
}
}
})
</script>
</body>
</html>`;

171
packages/nocodb/src/lib/services/userService/ui/emailTemplates/forgotPassword.ts

@ -0,0 +1,171 @@
export default `<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Transactional Email</title>
<style>
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important;
}
}
</style>
</head>
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">This is preheader text. Some clients will show this text as a preview.</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f6f6f6; width: 100%;" width="100%" bgcolor="#f6f6f6">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;" width="580" valign="top">
<div class="content" style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- START CENTERED WHITE CONTAINER -->
<table role="presentation" class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background: #ffffff; border-radius: 3px; width: 100%;" width="100%">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">Hi,</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">To change your NocoDB account password click the following link.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; box-sizing: border-box; width: 100%;" width="100%">
<tbody>
<tr>
<td align="left" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;" valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background-color: #3498db;" valign="top" align="center" bgcolor="#1088ff"> <a href="<%- resetLink %>" target="_blank" style="border: solid 1px rgb(23, 139, 255); border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-decoration: none; text-transform: capitalize; background-color: rgb(23, 139, 255); border-color: #3498db; color: #ffffff;">Reset Password</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">Thanks regards NocoDB.</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- END CENTERED WHITE CONTAINER -->
<!-- START FOOTER -->
<div class="footer" style="clear: both; margin-top: 10px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;" valign="top" align="center">
<span class="apple-link" style="color: #999999; font-size: 12px; text-align: center;"></span>
<!-- <br> Don't like these emails? <a href="http://i.imgur.com/CScmqnj.gif">Unsubscribe</a>.-->
</td>
</tr>
<tr>
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;" valign="top" align="center">
<a href="http://nocodb.com/">NocoDB</a>
<!-- Powered by <a href="http://htmlemail.io">HTMLemail</a>.-->
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
</div>
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
</tr>
</table>
</body>
</html>
`;

208
packages/nocodb/src/lib/services/userService/ui/emailTemplates/invite.ts

@ -0,0 +1,208 @@
export default `<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Transactional Email</title>
<style>
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important;
}
}
</style>
</head>
<body class=""
style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<span class="preheader"
style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">This is preheader text. Some clients will show this text as a preview.</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f6f6f6; width: 100%;"
width="100%" bgcolor="#f6f6f6">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
<td class="container"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;"
width="580" valign="top">
<div class="content"
style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- START CENTERED WHITE CONTAINER -->
<table role="presentation" class="main"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background: #ffffff; border-radius: 3px; width: 100%;"
width="100%">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;"
valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"
width="100%">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"
valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Hi,</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
I invited you to be "<%- roles -%>" of the NocoDB project "<%- projectName %>".
Click the button below to to accept my invitation.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
class="btn btn-primary"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; box-sizing: border-box; width: 100%;"
width="100%">
<tbody>
<tr>
<td align="left"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;"
valign="top">
<table role="presentation" border="0" cellpadding="0"
cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background-color: #3498db;"
valign="top" align="center" bgcolor="#1088ff"><a
href="<%- signupLink %>" target="_blank"
style="border: solid 1px rgb(23, 139, 255); border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-decoration: none; text-transform: capitalize; background-color: rgb(23, 139, 255); border-color: #3498db; color: #ffffff;">Signup</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Thanks regards <%- adminEmail %>.</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- END CENTERED WHITE CONTAINER -->
<!-- START FOOTER -->
<div class="footer" style="clear: both; margin-top: 10px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"
width="100%">
<tr>
<td class="content-block"
style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"
valign="top" align="center">
<span class="apple-link"
style="color: #999999; font-size: 12px; text-align: center;"></span>
<!-- <br> Don't like these emails? <a href="http://i.imgur.com/CScmqnj.gif">Unsubscribe</a>.-->
</td>
</tr>
<tr>
<td class="content-block powered-by"
style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"
valign="top" align="center">
<a href="http://nocodb.com/">NocoDB</a>
<!-- Powered by <a href="http://htmlemail.io">HTMLemail</a>.-->
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
</div>
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
</tr>
</table>
</body>
</html>
`;

207
packages/nocodb/src/lib/services/userService/ui/emailTemplates/verify.ts

@ -0,0 +1,207 @@
export default `<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Transactional Email</title>
<style>
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important;
}
}
</style>
</head>
<body class=""
style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
<span class="preheader"
style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">This is preheader text. Some clients will show this text as a preview.</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: #f6f6f6; width: 100%;"
width="100%" bgcolor="#f6f6f6">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
<td class="container"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; max-width: 580px; padding: 10px; width: 580px; margin: 0 auto;"
width="580" valign="top">
<div class="content"
style="box-sizing: border-box; display: block; margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- START CENTERED WHITE CONTAINER -->
<table role="presentation" class="main"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background: #ffffff; border-radius: 3px; width: 100%;"
width="100%">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;"
valign="top">
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"
width="100%">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"
valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Hi,</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Please verify your email address by clicking the following button.</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
class="btn btn-primary"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; box-sizing: border-box; width: 100%;"
width="100%">
<tbody>
<tr>
<td align="left"
style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;"
valign="top">
<table role="presentation" border="0" cellpadding="0"
cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
<tbody>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; border-radius: 5px; text-align: center; background-color: #3498db;"
valign="top" align="center" bgcolor="#1088ff"><a
href="<%- verifyLink %>" target="_blank"
style="border: solid 1px rgb(23, 139, 255); border-radius: 5px; box-sizing: border-box; cursor: pointer; display: inline-block; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-decoration: none; text-transform: capitalize; background-color: rgb(23, 139, 255); border-color: #3498db; color: #ffffff;">Verify</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; margin-bottom: 15px;">
Thanks regards NocoDB.</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- END CENTERED WHITE CONTAINER -->
<!-- START FOOTER -->
<div class="footer" style="clear: both; margin-top: 10px; text-align: center; width: 100%;">
<table role="presentation" border="0" cellpadding="0" cellspacing="0"
style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;"
width="100%">
<tr>
<td class="content-block"
style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"
valign="top" align="center">
<span class="apple-link"
style="color: #999999; font-size: 12px; text-align: center;"></span>
<!-- <br> Don't like these emails? <a href="http://i.imgur.com/CScmqnj.gif">Unsubscribe</a>.-->
</td>
</tr>
<tr>
<td class="content-block powered-by"
style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"
valign="top" align="center">
<a href="http://nocodb.com/">NocoDB</a>
<!-- Powered by <a href="http://htmlemail.io">HTMLemail</a>.-->
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
</div>
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
</tr>
</table>
</body>
</html>
`;

4
packages/nocodb/src/lib/services/utilService.ts

@ -20,9 +20,7 @@ const versionCache = {
lastFetched: null,
};
export async function testConnection(param:{body: any}) {
export async function testConnection(param: { body: any }) {
return await SqlMgrv2.testConnection(param.body);
}

8
packages/nocodb/src/lib/services/viewColumnService.ts

@ -1,5 +1,5 @@
import { Tele } from 'nc-help';
import { View } from '../models'
import { T } from 'nc-help';
import { View } from '../models';
export async function columnList(param: { viewId: string }) {
return await View.getColumns(param.viewId);
@ -18,7 +18,7 @@ export async function columnAdd(param: {
view_id: param.viewId,
}
);
Tele.emit('evt', { evt_type: 'viewColumn:inserted' });
T.emit('evt', { evt_type: 'viewColumn:inserted' });
return viewColumn;
}
@ -34,6 +34,6 @@ export async function columnUpdate(param: {
param.columnId,
param.column
);
Tele.emit('evt', { evt_type: 'viewColumn:updated' });
T.emit('evt', { evt_type: 'viewColumn:updated' });
return result;
}

32
packages/nocodb/src/lib/services/viewService.ts

@ -1,6 +1,6 @@
import { SharedViewType, ViewType } from 'nocodb-sdk';
import { Model, View } from '../models';
import { Tele } from 'nc-help';
import { SharedViewReqType, ViewReqType } from 'nocodb-sdk';
import { T } from 'nc-help';
import { xcVisibilityMetaGet } from './modelVisibilityService';
export async function viewList(param: {
@ -11,12 +11,10 @@ export async function viewList(param: {
}) {
const model = await Model.get(param.tableId);
const viewList = await xcVisibilityMetaGet(
// param.projectId,
// param.baseId,
model.project_id,
[model]
);
const viewList = await xcVisibilityMetaGet({
projectId: model.project_id,
models: [model],
});
// todo: user roles
//await View.list(param.tableId)
@ -31,34 +29,34 @@ export async function viewList(param: {
// @ts-ignore
export async function shareView(param: { viewId: string }) {
Tele.emit('evt', { evt_type: 'sharedView:generated-link' });
T.emit('evt', { evt_type: 'sharedView:generated-link' });
return await View.share(param.viewId);
}
// @ts-ignore
export async function viewUpdate(param: { viewId: string; view: ViewReqType }) {
// todo: type correctly
export async function viewUpdate(param: { viewId: string; view: ViewType }) {
const result = await View.update(param.viewId, param.view);
Tele.emit('evt', { evt_type: 'vtable:updated', show_as: result.type });
T.emit('evt', { evt_type: 'vtable:updated', show_as: result.type });
return result;
}
// @ts-ignore
export async function viewDelete(param: { viewId: string }) {
await View.delete(param.viewId);
Tele.emit('evt', { evt_type: 'vtable:deleted' });
T.emit('evt', { evt_type: 'vtable:deleted' });
return true;
}
export async function shareViewUpdate(param: {
viewId: string;
sharedView: SharedViewReqType;
// todo: type correctly
sharedView: SharedViewType;
}) {
Tele.emit('evt', { evt_type: 'sharedView:updated' });
T.emit('evt', { evt_type: 'sharedView:updated' });
return await View.update(param.viewId, param.sharedView);
}
export async function shareViewDelete(param: { viewId: string }) {
Tele.emit('evt', { evt_type: 'sharedView:deleted' });
T.emit('evt', { evt_type: 'sharedView:deleted' });
await View.sharedViewDelete(param.viewId);
return true;
}

6
packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts

@ -21,7 +21,7 @@ import NcProjectBuilder from '../../v1-legacy/NcProjectBuilder';
import Noco from '../../Noco';
import NcMetaIO from '../../meta/NcMetaIO';
import XcCache from '../../v1-legacy/plugins/adapters/cache/XcCache';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import BaseModel from './BaseModel';
import { XcCron } from './XcCron';
@ -324,7 +324,7 @@ export default abstract class BaseApiBuilder<T extends Noco>
}
);
}
Tele.emit('evt', { evt_type: 'relation:created' });
T.emit('evt', { evt_type: 'relation:created' });
}
public async onRelationDelete(
@ -2979,7 +2979,7 @@ export default abstract class BaseApiBuilder<T extends Noco>
}
public async onTableCreate(_tn: string, _args?: any) {
Tele.emit('evt', { evt_type: 'table:created' });
T.emit('evt', { evt_type: 'table:created' });
}
public onVirtualTableUpdate(args: any) {

4
packages/nocodb/src/lib/v1-legacy/NcProjectBuilder.ts

@ -10,7 +10,7 @@ import SqlClientFactory from '../db/sql-client/lib/SqlClientFactory';
import Migrator from '../db/sql-migrator/lib/KnexMigrator';
import Noco from '../Noco';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import { GqlApiBuilder } from './gql/GqlApiBuilder';
import { XCEeError } from '../meta/NcMetaMgr';
import { RestApiBuilder } from './rest/RestApiBuilder';
@ -840,7 +840,7 @@ export default class NcProjectBuilder {
this.apiInfInfoList.push(info);
this.aggregatedApiInfo = aggregatedInfo;
if (isFirstTime) {
Tele.emit('evt_api_created', info);
T.emit('evt_api_created', info);
}
}

18
packages/nocodb/src/lib/v1-legacy/rest/RestAuthCtrl.ts

@ -29,7 +29,7 @@ const { isEmail } = require('validator');
import axios from 'axios';
import IEmailAdapter from '../../../interface/IEmailAdapter';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import XcCache from '../plugins/adapters/cache/XcCache';
passport.serializeUser(function (
@ -130,7 +130,7 @@ export default class RestAuthCtrl {
await this.createAuthTableIfNotExists();
await this.initStrategies();
Tele.emit('evt_app_started', await this.users.count('id as count').first());
T.emit('evt_app_started', await this.users.count('id as count').first());
this.app.router.use(passport.initialize());
const jwtMiddleware = passport.authenticate('jwt', { session: false });
@ -406,7 +406,7 @@ export default class RestAuthCtrl {
const token = req.query.state;
if (token) {
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
await this.users
.update({
// firstname, lastname,
@ -431,7 +431,7 @@ export default class RestAuthCtrl {
return cb({ msg: `Account not found!` });
}
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
const salt = await promisify(bcrypt.genSalt)(10);
user = await this.users.insert({
email: profile.emails[0].value,
@ -513,7 +513,7 @@ export default class RestAuthCtrl {
const token = req.query?.state?.replace('github|', '');
if (token) {
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
await this.users
.update({
// firstname, lastname,
@ -538,7 +538,7 @@ export default class RestAuthCtrl {
return cb({ msg: `Account not found!` });
}
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
const salt = await promisify(bcrypt.genSalt)(10);
user = await this.users.insert({
email: profile.emails[0].value,
@ -900,7 +900,7 @@ export default class RestAuthCtrl {
const email_verification_token = uuidv4();
if (!ignore_subscribe) {
Tele.emit('evt_subscribe', email);
T.emit('evt_subscribe', email);
}
if (user) {
@ -928,7 +928,7 @@ export default class RestAuthCtrl {
if (!(await this.users.first())) {
// todo: update in nc_store
// roles = 'owner,creator,editor'
Tele.emit('evt', { evt_type: 'project:invite', count: 1 });
T.emit('evt', { evt_type: 'project:invite', count: 1 });
} else {
if (process.env.NC_INVITE_ONLY_SIGNUP) {
return next(
@ -1289,7 +1289,7 @@ export default class RestAuthCtrl {
}
}
Tele.emit('evt', { evt_type: 'project:invite', count: count?.count });
T.emit('evt', { evt_type: 'project:invite', count: count?.count });
this.xcMeta.audit(req.body.project_id, null, 'nc_audit', {
op_type: 'AUTHENTICATION',
op_sub_type: 'INVITE',

4
packages/nocodb/src/lib/v1-legacy/rest/RestAuthCtrlEE.ts

@ -2,7 +2,7 @@ import passport from 'passport';
import { Strategy } from 'passport-jwt';
import { v4 as uuidv4 } from 'uuid';
import validator from 'validator';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import XcCache from '../plugins/adapters/cache/XcCache';
@ -85,7 +85,7 @@ export default class RestAuthCtrlEE extends RestAuthCtrl {
req.body.roles
);
Tele.emit('evt', { evt_type: 'project:invite', count: count?.count });
T.emit('evt', { evt_type: 'project:invite', count: count?.count });
this.xcMeta.audit(req.body.project_id, null, 'nc_audit', {
op_type: 'AUTHENTICATION',

6
packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts

@ -2,7 +2,7 @@ import { NcConfig } from '../../interface/config';
import debug from 'debug';
import NcMetaIO from '../meta/NcMetaIO';
import { Tele } from 'nc-help';
import { T } from 'nc-help';
import ncProjectEnvUpgrader from './ncProjectEnvUpgrader';
import ncProjectEnvUpgrader0011045 from './ncProjectEnvUpgrader0011045';
import ncProjectUpgraderV2_0090000 from './ncProjectUpgraderV2_0090000';
@ -107,14 +107,14 @@ export default class NcUpgrader {
}
}
await ctx.ncMeta.commit();
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'appMigration:upgraded',
from: oldVersion,
to: process.env.NC_VERSION,
});
} catch (e) {
await ctx.ncMeta.rollback(e);
Tele.emit('evt', {
T.emit('evt', {
evt_type: 'appMigration:failed',
from: oldVersion,
to: process.env.NC_VERSION,

Loading…
Cancel
Save