-
Notifications
You must be signed in to change notification settings - Fork 195
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
feat: Add integration with: Sharepoint #693
Changes from 5 commits
7102605
773227f
a68dc6d
9252f51
5ad0523
091e72f
74fac19
4409e9d
b938345
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -265,7 +265,10 @@ function updateModuleFileForMapper(moduleFile, newServiceDirs, objectType) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Generate and insert new service imports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
newServiceDirs.forEach((serviceName) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const mapperClass = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceName.charAt(0).toUpperCase() + serviceName.slice(1) + objectType + 'Mapper'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceName.charAt(0).toUpperCase() + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceName.slice(1) + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
objectType + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'Mapper'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const importStatement = `import { ${mapperClass} } from './services/${serviceName}/mappers';\n`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!moduleFileContent.includes(importStatement)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
moduleFileContent = importStatement + moduleFileContent; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -404,17 +407,20 @@ function updateSeedSQLFile(seedSQLFile, newServiceDirs, vertical) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fileContent = fileContent.replace(lastMatch[1], newColumnsSection); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Update each VALUES section | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fileContent = fileContent.replace(/INSERT INTO connector_sets \(([^)]+)\) VALUES(.*?);/gs, (match) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return match | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.replace(/\),\s*\(/g, '),\n (') // Fix line formatting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.replace(/\([^\)]+\)/g, (values, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (values.startsWith('(id_connector_set')) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return values | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let newValues = newColumns.map(() => 'TRUE').join(', '); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return values.slice(0, -1) + ', ' + newValues + ')'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fileContent = fileContent.replace( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/INSERT INTO connector_sets \(([^)]+)\) VALUES(.*?);/gs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(match) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return match | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.replace(/\),\s*\(/g, '),\n (') // Fix line formatting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
.replace(/\([^\)]+\)/g, (values, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (values.startsWith('(id_connector_set')) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return values; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let newValues = newColumns.map(() => 'TRUE').join(', '); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return values.slice(0, -1) + ', ' + newValues + ')'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor to use template literals in SQL string manipulation. The current implementation uses complex string concatenation which can be simplified using template literals. This will improve the readability and maintainability of the code. Here's the suggested change: -let newValues = newColumns.map(() => 'TRUE').join(', ');
-return values.slice(0, -1) + ', ' + newValues + ')';
+let newValues = newColumns.map(() => 'TRUE').join(', ');
+return `${values.slice(0, -1)}, ${newValues})`; Committable suggestion
Suggested change
ToolsBiome
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Write the modified content back to the file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(fileContent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -427,9 +433,10 @@ function updateSeedSQLFile(seedSQLFile, newServiceDirs, vertical) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function updateObjectTypes(baseDir, objectType, vertical) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const servicesDir = path.join(__dirname, baseDir); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const targetFilename = vertical == 'filestorage' ? 'file-storage' : vertical; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const targetFile = path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
__dirname, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`../src/@core/utils/types/original/original.${vertical}.ts`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`../src/@core/utils/types/original/original.${targetFilename}.ts`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const newServiceDirs = scanDirectory(servicesDir); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -468,7 +475,7 @@ function updateObjectTypes(baseDir, objectType, vertical) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateModuleFileForService(moduleFile, newServiceDirs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateModuleFileForMapper(moduleFile, newServiceDirs, objectType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateModuleFileForMapper(moduleFile, newServiceDirs, objectType); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Path to the mappings file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// const mappingsFile = path.join( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -522,4 +529,4 @@ if (import.meta.url === process.argv[1]) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const argv = yargs(hideBin(process.argv)).argv; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const baseDir = `../src/${argv.vertical.toLowerCase()}/${argv.objectType.toLowerCase()}/services`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateObjectTypes(baseDir, argv.objectType, argv.vertical); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateObjectTypes(baseDir, argv.objectType, argv.vertical); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -538,6 +538,7 @@ export class CoreSyncService { | |
try { | ||
await task(); | ||
} catch (error) { | ||
console.log(error); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider removing Using |
||
this.logger.error(`File Storage Task failed: ${error.message}`, error); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service'; | ||
import { LoggerService } from '@@core/@core-services/logger/logger.service'; | ||
import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; | ||
import { ApiResponse } from '@@core/utils/types'; | ||
import { SyncParam } from '@@core/utils/types/interface'; | ||
import { FileStorageObject } from '@filestorage/@lib/@types'; | ||
import { IDriveService } from '@filestorage/drive/types'; | ||
import { Injectable } from '@nestjs/common'; | ||
import axios from 'axios'; | ||
import { ServiceRegistry } from '../registry.service'; | ||
import { SharepointDriveOutput } from './types'; | ||
import { DesunifyReturnType } from '@@core/utils/types/desunify.input'; | ||
import { OriginalDriveOutput } from '@@core/utils/types/original/original.file-storage'; | ||
|
||
@Injectable() | ||
export class SharepointService implements IDriveService { | ||
constructor( | ||
private prisma: PrismaService, | ||
private logger: LoggerService, | ||
private cryptoService: EncryptionService, | ||
private registry: ServiceRegistry, | ||
) { | ||
this.logger.setContext( | ||
`${FileStorageObject.file.toUpperCase()}:${SharepointService.name}`, | ||
); | ||
this.registry.registerService('sharepoint', this); | ||
} | ||
|
||
async addDrive( | ||
driveData: DesunifyReturnType, | ||
linkedUserId: string, | ||
): Promise<ApiResponse<OriginalDriveOutput>> { | ||
// No API to add drive in Sharepoint | ||
return; | ||
} | ||
Comment on lines
+29
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clarify the stub for The |
||
|
||
async sync(data: SyncParam): Promise<ApiResponse<SharepointDriveOutput[]>> { | ||
try { | ||
const { linkedUserId } = data; | ||
|
||
const connection = await this.prisma.connections.findFirst({ | ||
where: { | ||
id_linked_user: linkedUserId, | ||
provider_slug: 'sharepoint', | ||
vertical: 'filestorage', | ||
}, | ||
}); | ||
|
||
const resp = await axios.get(`${connection.account_url}/drives`, { | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: `Bearer ${this.cryptoService.decrypt( | ||
connection.access_token, | ||
)}`, | ||
}, | ||
}); | ||
|
||
const drives: SharepointDriveOutput[] = resp.data.value; | ||
this.logger.log(`Synced sharepoint drives !`); | ||
|
||
return { | ||
data: drives, | ||
message: 'Sharepoint drives retrived', | ||
statusCode: 200, | ||
}; | ||
} catch (error) { | ||
console.log(error.response); | ||
throw error; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry'; | ||
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service'; | ||
import { Utils } from '@filestorage/@lib/@utils'; | ||
import { | ||
UnifiedFilestorageDriveInput, | ||
UnifiedFilestorageDriveOutput, | ||
} from '@filestorage/drive/types/model.unified'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { SharepointDriveInput, SharepointDriveOutput } from './types'; | ||
import { IDriveMapper } from '@filestorage/drive/types'; | ||
|
||
@Injectable() | ||
export class SharepointDriveMapper implements IDriveMapper { | ||
constructor( | ||
private mappersRegistry: MappersRegistry, | ||
private utils: Utils, | ||
private coreUnificationService: CoreUnification, | ||
) { | ||
this.mappersRegistry.registerService( | ||
'filestorage', | ||
'drive', | ||
'sharepoint', | ||
this, | ||
); | ||
} | ||
|
||
async desunify( | ||
source: UnifiedFilestorageDriveInput, | ||
customFieldMappings?: { | ||
slug: string; | ||
remote_id: string; | ||
}[], | ||
): Promise<SharepointDriveInput> { | ||
return; | ||
Comment on lines
+27
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incomplete implementation of The Would you like me to help draft the implementation or should this be tracked as a task in your project management tool? |
||
} | ||
|
||
async unify( | ||
source: SharepointDriveOutput | SharepointDriveOutput[], | ||
connectionId: string, | ||
customFieldMappings?: { | ||
slug: string; | ||
remote_id: string; | ||
}[], | ||
): Promise<UnifiedFilestorageDriveOutput | UnifiedFilestorageDriveOutput[]> { | ||
if (!Array.isArray(source)) { | ||
return await this.mapSingleDriveToUnified( | ||
source, | ||
connectionId, | ||
customFieldMappings, | ||
); | ||
} | ||
// Handling array of SharepointDriveOutput | ||
return Promise.all( | ||
source.map((drive) => | ||
this.mapSingleDriveToUnified(drive, connectionId, customFieldMappings), | ||
), | ||
); | ||
} | ||
|
||
private async mapSingleDriveToUnified( | ||
drive: SharepointDriveOutput, | ||
connectionId: string, | ||
customFieldMappings?: { | ||
slug: string; | ||
remote_id: string; | ||
}[], | ||
): Promise<UnifiedFilestorageDriveOutput> { | ||
const field_mappings: { [key: string]: any } = {}; | ||
if (customFieldMappings) { | ||
for (const mapping of customFieldMappings) { | ||
field_mappings[mapping.slug] = drive[mapping.remote_id]; | ||
} | ||
} | ||
|
||
const result: UnifiedFilestorageDriveOutput = { | ||
remote_id: drive.id, | ||
remote_data: drive, | ||
name: drive.name, | ||
remote_created_at: drive.createdDateTime, | ||
drive_url: drive.webUrl, | ||
field_mappings, | ||
}; | ||
|
||
return result; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use template literals for string concatenation.
To enhance readability and maintainability, consider using template literals instead of string concatenation. This change aligns with modern JavaScript practices and addresses the static analysis tool's suggestion.
Here's the suggested change:
Committable suggestion
Tools
Biome