mirror of https://github.com/nocodb/nocodb
starbirdtech383
2 years ago
6 changed files with 334 additions and 20 deletions
@ -0,0 +1,68 @@
|
||||
/** |
||||
* Compare obj1 and obj2 conditionally based on ignoredFields set |
||||
* Ignore the field names which are passed in the ignoredFields. |
||||
* optionally keyId will be use to prefix the keys mismatched |
||||
* |
||||
* |
||||
* use utility boolean param breakAtFirstMismatch to print diff for |
||||
* all the fields instead of breaking at first mismatch |
||||
* |
||||
* @param obj1 |
||||
* @param obj2 |
||||
* @param ignoredFields : filed names ex: title |
||||
* @param ignoredKeys : json path for the filed ex: ".project.is_meta.title" |
||||
* @param keyId : starts with "" |
||||
* @param breakAtFirstMismatch : default true. returns false on first field mismatch |
||||
* @returns |
||||
*/ |
||||
export function deepCompare( |
||||
obj1: any, |
||||
obj2: any, |
||||
ignoredFields?: Set<string>, |
||||
ignoredKeys?: Set<string>, |
||||
keyId = '', |
||||
breakAtFirstMismatch = true |
||||
): boolean { |
||||
if (ignoredKeys !== undefined && ignoredKeys.has(keyId)) { |
||||
return true; |
||||
} |
||||
// If the objects are the same instance, they are equal
|
||||
if (obj1 === obj2) { |
||||
return true; |
||||
} |
||||
|
||||
// If one of the objects is null or not an object, they are not equal
|
||||
if (!obj1 || !obj2 || typeof obj1 !== 'object' || typeof obj2 !== 'object') { |
||||
console.log(`Mismatch key: ${keyId} value1: "${obj1}" value2: "${obj2}"`); |
||||
return !breakAtFirstMismatch; |
||||
// return false;
|
||||
} |
||||
|
||||
// If the objects have different numbers of properties, they are not equal
|
||||
const keys1 = Object.keys(obj1); |
||||
const keys2 = Object.keys(obj2); |
||||
if (keys1.length !== keys2.length) { |
||||
console.log(`Mismatch length key: ${keyId} value1: "${obj1}" value2: "${obj2}"`); |
||||
return !breakAtFirstMismatch; |
||||
// return false;
|
||||
} |
||||
|
||||
// Recursively compare each property of the objects
|
||||
for (const key of keys1) { |
||||
if ( |
||||
(ignoredFields !== undefined && ignoredFields.has(key)) || |
||||
key.endsWith(' List') /* temp hack to avoid fields like */ |
||||
) { |
||||
// console.log(`${keyId} ignored in comparison`)
|
||||
} else { |
||||
keyId = keyId + '.' + key; |
||||
if (!deepCompare(obj1[key], obj2[key], ignoredFields, ignoredKeys, keyId, breakAtFirstMismatch)) { |
||||
return !breakAtFirstMismatch; |
||||
// return false;
|
||||
} |
||||
} |
||||
} |
||||
|
||||
// If all properties match, the objects are equal
|
||||
return true; |
||||
} |
@ -0,0 +1,167 @@
|
||||
import { |
||||
Api, |
||||
BaseListType, |
||||
BaseType, |
||||
FilterListType, |
||||
FilterType, |
||||
HookListType, |
||||
HookType, |
||||
PaginatedType, |
||||
ProjectType, |
||||
SharedViewListType, |
||||
SharedViewType, |
||||
SignInReqType, |
||||
SortListType, |
||||
SortType, |
||||
TableListType, |
||||
TableType, |
||||
UserType, |
||||
ViewListType, |
||||
ViewType, |
||||
} from 'nocodb-sdk'; |
||||
|
||||
export class ViewInfo { |
||||
view: ViewType; |
||||
filters: FilterType[]; |
||||
sorts: SortType[]; |
||||
firstPageData?: { |
||||
/** List of data objects */ |
||||
list: any[]; |
||||
/** Paginated Info */ |
||||
pageInfo: PaginatedType; |
||||
}; |
||||
} |
||||
|
||||
export class TableInfo { |
||||
table: TableType; |
||||
views: ViewInfo[]; |
||||
shares: SharedViewType[]; |
||||
webhooks: HookType[]; |
||||
firstPageData?: { |
||||
/** List of data objects */ |
||||
list: any[]; |
||||
/** Paginated Info */ |
||||
pageInfo: PaginatedType; |
||||
}; |
||||
} |
||||
|
||||
export class ProjectInfo { |
||||
project: ProjectType; |
||||
bases: BaseType[]; |
||||
users: UserType[]; |
||||
tables: TableInfo[]; |
||||
} |
||||
|
||||
export class ProjectInfoOperator { |
||||
api: Api<any>; |
||||
|
||||
constructor(token: string) { |
||||
this.api = new Api({ |
||||
baseURL: `http://localhost:8080/`, |
||||
headers: { |
||||
'xc-auth': token, |
||||
}, |
||||
}); |
||||
} |
||||
/** |
||||
* extracts the projectInfo using sdk via apis |
||||
* |
||||
* @param projectId |
||||
* @returns |
||||
*/ |
||||
async extractProjectData(projectId: string): Promise<ProjectInfo> { |
||||
// TODO: capture apiTokens, projectSettings, ACLVisibilityRules, UI ACL (discuss before adding)
|
||||
const project: ProjectType = await this.api.project.read(projectId); |
||||
// bases
|
||||
const bases: BaseListType = await this.api.base.list(projectId); |
||||
// users
|
||||
const usersWrapper: any = await this.api.auth.projectUserList(projectId); |
||||
|
||||
// SET project, users and bases
|
||||
const projectInfo: ProjectInfo = { project: project, tables: [], bases: [], users: [] }; |
||||
projectInfo.bases = bases.list; |
||||
if (usersWrapper.users) { |
||||
projectInfo.users = usersWrapper.users.list as UserType[]; |
||||
} |
||||
|
||||
const tables: TableListType = await this.api.dbTable.list(projectId); |
||||
for (const table of tables.list) { |
||||
const tableInfo: TableInfo = { table: table, shares: [], views: [], webhooks: [] }; |
||||
const views: ViewListType = await this.api.dbView.list(table.id); |
||||
for (const v of views.list) { |
||||
const filters: FilterListType = await this.api.dbTableFilter.read(v.id); |
||||
const sorts: SortListType = await this.api.dbTableSort.list(v.id); |
||||
|
||||
// create ViewData and push to array
|
||||
const viewInfo: ViewInfo = { view: v, filters: [], sorts: [] }; |
||||
viewInfo.firstPageData = await this.api.dbViewRow.list('noco', projectId, table.id, v.id); |
||||
viewInfo.filters = filters.list; |
||||
viewInfo.sorts = sorts.list; |
||||
tableInfo.views.push(viewInfo); |
||||
} |
||||
const shares: SharedViewListType = await this.api.dbViewShare.list(table.id); |
||||
const webhooks: HookListType = await this.api.dbTableWebhook.list(table.id); |
||||
tableInfo.shares = shares.list; |
||||
tableInfo.webhooks = webhooks.list; |
||||
projectInfo.tables.push(tableInfo); |
||||
tableInfo.firstPageData = await this.api.dbTableRow.list('noco', projectId, table.id); |
||||
} |
||||
return projectInfo; |
||||
} |
||||
|
||||
/** |
||||
* helper function to print projectInfo |
||||
* do not use this function to assert anything. |
||||
* this is only helper function to debug and should |
||||
* be allowed to modify without any test failures. |
||||
* |
||||
* @param projectData |
||||
*/ |
||||
async printProjectData(projectData: ProjectInfo) { |
||||
console.log('project.title : ' + projectData.project.title); |
||||
// bases
|
||||
console.log('Bases:'); |
||||
for (const base of projectData.bases) { |
||||
console.log(base.id); |
||||
} |
||||
// users
|
||||
console.log('Users:'); |
||||
if (projectData.users) { |
||||
for (const user of projectData.users) { |
||||
console.log(user.email); |
||||
} |
||||
} |
||||
console.log('Tables: '); |
||||
|
||||
if (projectData.tables) { |
||||
for (const tableData of projectData.tables) { |
||||
console.log('Table: ' + tableData.table.title); |
||||
console.log('Views: '); |
||||
|
||||
console.log('Filters: '); |
||||
for (const viewData of tableData.views) { |
||||
const v: ViewType = viewData.view; |
||||
console.log(`${v.title} ${v.id}`); |
||||
if (viewData.filters.length > 0) { |
||||
console.log('======= Filters ======='); |
||||
console.log(viewData.filters); |
||||
} |
||||
if (viewData.sorts.length > 0) { |
||||
console.log('======= Sorts ======='); |
||||
console.log(viewData.sorts); |
||||
} |
||||
} |
||||
|
||||
if (tableData.shares.length > 0) { |
||||
console.log('======= Shares ======='); |
||||
console.log(tableData.shares.forEach(s => console.log(s.uuid))); |
||||
} |
||||
|
||||
if (tableData.webhooks.length > 0) { |
||||
console.log('======= Webhooks ======='); |
||||
console.log(tableData.webhooks.forEach(w => console.log(w.id))); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue