Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ericbrehault/sc 8739/store origin path for all sync connectors #14

Merged
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
run: npm run compile
working-directory: server

- name: build
env:
CI: false
run: npm run make
# - name: build
# env:
# CI: false
# run: npm run make
38 changes: 25 additions & 13 deletions electron-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion electron-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"license": "MIT",
"dependencies": {
"@nuclia/core": "1.9.0",
"@nuclia/core": "^1.11.6",
"cheerio": "^1.0.0-rc.12",
"commander": "^11.1.0",
"compression": "^1.7.4",
Expand Down
8 changes: 4 additions & 4 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"start-server": "npm run compile && node build/start-file-system-server.js"
},
"dependencies": {
"@nuclia/core": "1.9.1",
"@nuclia/core": "^1.11.6",
"cheerio": "^1.0.0-rc.12",
"commander": "^11.1.0",
"compression": "^1.7.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class ConfluenceImpl implements IConnector {
return {
title: (isFolder ? raw.name : raw.title) || '',
originalId: (isFolder ? raw.key : itemOriginalId) || '',
metadata: { type: raw.type || '' },
metadata: { type: raw.type || '', path: raw._links?.webui || '' },
status: FileStatus.PENDING,
uuid: `${raw.id}` || '',
isFolder: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ export class DropboxImpl extends OAuthBaseConnector implements IConnector {
return {
title: raw.name || '',
originalId: (isFolder ? raw.path_lower : raw.id) || '',
metadata: {},
metadata: {
path: raw.path_lower.split('/').slice(0, -1).join('/'),
},
status: FileStatus.PENDING,
uuid: (isFolder ? raw.path_lower : raw.id) || '',
modifiedGMT: raw.client_modified,
Expand All @@ -202,7 +204,9 @@ export class DropboxImpl extends OAuthBaseConnector implements IConnector {
return {
title: raw.metadata?.metadata?.['name'] || '',
originalId: raw.metadata?.metadata?.['id'] || '',
metadata: {},
metadata: {
path: raw.path_lower.split('/').slice(0, -1).join('/'),
},
status: FileStatus.PENDING,
uuid: raw.metadata?.metadata?.['uuid'] || '',
isFolder: raw.match_type?.['.tag'] === 'folder',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ class FolderImpl implements IConnector {
return files.map((file) => ({
title: file.split('/').pop() || '',
originalId: file,
metadata: {},
metadata: {
path: file.split('/').slice(0, -1).join('/'),
},
status: FileStatus.PENDING,
uid: '',
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { catchError, concatMap, forkJoin, from, map, Observable, of } from 'rxjs';
import { Observable, catchError, concatMap, forkJoin, from, map, of, switchMap } from 'rxjs';

import { ConnectorParameters, FileStatus, IConnector, Link, SearchResults, SyncItem } from '../../domain/connector';
import { SourceConnectorDefinition } from '../factory';
Expand Down Expand Up @@ -48,7 +48,7 @@ export class GDriveImpl extends OAuthBaseConnector implements IConnector {
});
}
try {
return forkJoin((folders || []).map((folder) => this._getItems('', folder.uuid))).pipe(
return forkJoin((folders || []).map((folder) => this._getFileItems('', folder.uuid))).pipe(
map((results) => {
const items = results.reduce(
(acc, result) => acc.concat(result.items.filter((item) => item.modifiedGMT && item.modifiedGMT > since)),
Expand All @@ -73,7 +73,7 @@ export class GDriveImpl extends OAuthBaseConnector implements IConnector {
});
}
try {
return forkJoin((folders || []).map((folder) => this._getItems('', folder.uuid))).pipe(
return forkJoin((folders || []).map((folder) => this._getFileItems('', folder.uuid))).pipe(
map((results) => {
const result: { items: SyncItem[] } = {
items: [],
Expand All @@ -96,7 +96,7 @@ export class GDriveImpl extends OAuthBaseConnector implements IConnector {
}

getFiles(query?: string): Observable<SearchResults> {
return this._getItems(query);
return this._getFileItems(query);
}

isAccessTokenValid(): Observable<boolean> {
Expand Down Expand Up @@ -125,6 +125,77 @@ export class GDriveImpl extends OAuthBaseConnector implements IConnector {
);
}

private getSubFolders(folders: SearchResults, folderId: string): string[] {
const getChildren = (folderId: string) => {
return folders.items.filter((item) => item.parents?.includes(folderId)).map((item) => item.originalId);
};
const children = getChildren(folderId);
return children.reduce((acc, child) => [...acc, ...getChildren(child)], children);
}

private _getFileItems(query = '', folder = ''): Observable<SearchResults> {
return this.getFolders().pipe(
switchMap((folders) => {
if (folder) {
const allTargetedFolders = [folder, ...this.getSubFolders(folders, folder)];
return forkJoin(allTargetedFolders.map((folder) => this._getItems(query, folder, false))).pipe(
map((results) => {
const items = results.reduce((acc, result) => acc.concat(result.items), [] as SyncItem[]);
return {
files: {
items,
},
folders,
};
}),
);
} else {
return this._getItems(query, '', false).pipe(map((results) => ({ files: results, folders })));
}
}),
map(({ files, folders }) => {
const getFolder = (folderId: string) => {
return folders.items.find((folder) => folder.originalId === folderId);
};
const parents = folders.items.reduce(
(acc, folder) => {
if (folder.parents) {
acc[folder.originalId] = folder.parents[0];
}
return acc;
},
{} as { [key: string]: string },
);
const getFolderPath = (folderId: string | undefined) => {
if (!folderId) {
return [];
}
let path: string[] = [];
let currentFolder = getFolder(folderId);
while (currentFolder) {
path = [currentFolder.title, ...path];
if (!parents[currentFolder.originalId]) {
break;
}
currentFolder = getFolder(parents[currentFolder.originalId]);
}
return path;
};
const itemsWithPath = files.items.map((item) => ({
...item,
metadata: {
...item.metadata,
path: getFolderPath(item.parents?.[0]).join('/'),
},
}));
return {
...files,
items: itemsWithPath,
};
}),
);
}

// Script create the tree https://gist.github.com/tanaikech/97b336f04c739ae0181a606eab3dff42
private _getItems(
query = '',
Expand All @@ -148,7 +219,6 @@ export class GDriveImpl extends OAuthBaseConnector implements IConnector {
if (nextPage) {
path += `&pageToken=${nextPage}`;
}

return from(
fetch(path, {
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,28 @@ export class OneDriveImpl extends OAuthBaseConnector implements IConnector {
);
}

private _getItems(
private _getItems(query = '', folder = '', foldersOnly = false, previous?: SearchResults): Observable<SearchResults> {
return this._getOneDriveItems(query, folder, foldersOnly, undefined, previous).pipe(
map((res) => {
const items = (res.value || [])
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.filter((item: any) => foldersOnly || !!item.file)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map((item: any) => (foldersOnly ? this.mapToSyncItemFolder(item) : this.mapToSyncItem(item)));
return { items };
}),
);
}

private _getOneDriveItems(
query = '',
folder = '',
foldersOnly = false,
nextPage?: string,
previous?: SearchResults,
): Observable<SearchResults> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
previous?: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Observable<any> {
let path = `https://graph.microsoft.com/v1.0/me/drive/${folder ? `items/${folder}` : 'root'}`;
if (query) {
path += `/search(q='${query}')`;
Expand Down Expand Up @@ -167,16 +182,27 @@ export class OneDriveImpl extends OAuthBaseConnector implements IConnector {
res['@odata.nextLink'] && res['@odata.nextLink'].includes('&$skiptoken=')
? res?.['@odata.nextLink'].split('&$skiptoken=')[1].split('&')[0]
: undefined;
const items = (res.value || [])
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.filter((item: any) => foldersOnly || !!item.file)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map((item: any) => (foldersOnly ? this.mapToSyncItemFolder(item) : this.mapToSyncItem(item)));
const results = {
items: [...(previous?.items || []), ...items],
nextPage,
};
return nextPage ? this._getItems(query, folder, foldersOnly, nextPage, results) : of(results);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const folders: string[] = (res.value || []).filter((item: any) => !!item.folder).map((item: any) => item.id);
const results = { ...res, value: [...(previous?.value || []), ...(res?.value || [])] };
const currentFolderResults = nextPage
? this._getOneDriveItems(query, folder, foldersOnly, nextPage, results)
: of(results);
if (folders.length === 0) {
return currentFolderResults;
} else {
return forkJoin([
currentFolderResults,
...folders.map((subfolder) => this._getOneDriveItems(query, subfolder, foldersOnly)),
]).pipe(
map((subresults) =>
subresults.reduce(
(acc, subresult) => ({ ...acc, value: [...(acc.value || []), ...(subresult.value || [])] }),
{},
),
),
);
}
}
}),
);
Expand All @@ -189,7 +215,11 @@ export class OneDriveImpl extends OAuthBaseConnector implements IConnector {
title: item.name,
originalId: item.id,
modifiedGMT: item.lastModifiedDateTime,
metadata: { mimeType: item.file.mimeType, downloadLink: item['@microsoft.graph.downloadUrl'] },
metadata: {
mimeType: item.file.mimeType,
downloadLink: item['@microsoft.graph.downloadUrl'],
path: item.parentReference.path,
},
status: FileStatus.PENDING,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class SitemapImpl implements IConnector {
originalId: parsedUrl.loc,
metadata: {
uri: parsedUrl.loc,
path: parsedUrl.loc.replace(/https?:\/\//, ''),
lastModified: parsedUrl.lastmod,
},
})),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ describe('Test last modified', () => {
metadata: {
needsPdfConversion: 'yes',
mimeType: 'application/pdf',
path: '',
},
status: FileStatus.PENDING,
},
Expand Down
Loading
Loading