Skip to content

Commit

Permalink
✨ Add github objects {User,Tag,Team,Collection}
Browse files Browse the repository at this point in the history
  • Loading branch information
mit-27 committed Jul 23, 2024
1 parent 54f87a3 commit ef976f7
Show file tree
Hide file tree
Showing 15 changed files with 985 additions and 0 deletions.
61 changes: 61 additions & 0 deletions packages/api/src/ticketing/collection/services/github/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Injectable } from '@nestjs/common';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { TicketingObject } from '@ticketing/@lib/@types';
import { ApiResponse } from '@@core/utils/types';
import axios from 'axios';
import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
import { ServiceRegistry } from '../registry.service';
import { ICollectionService } from '@ticketing/collection/types';
import { GithubCollectionInput, GithubCollectionOutput } from './types';
import { SyncParam } from '@@core/utils/types/interface';

@Injectable()
export class GithubService implements ICollectionService {
constructor(
private prisma: PrismaService,
private logger: LoggerService,
private cryptoService: EncryptionService,
private registry: ServiceRegistry,
) {
this.logger.setContext(
TicketingObject.collection.toUpperCase() + ':' + GithubService.name,
);
this.registry.registerService('github', this);
}

async sync(data: SyncParam): Promise<ApiResponse<GithubCollectionOutput[]>> {
try {
const { linkedUserId } = data;

const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'github',
vertical: 'ticketing',
},
});
const resp = await axios.get(
`${connection.account_url}/user/repos`,
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
},
);
this.logger.log(`Synced github collections !`);

return {
data: resp.data,
message: 'Github collections retrieved',
statusCode: 200,
};
} catch (error) {
throw error;
}
}
}
69 changes: 69 additions & 0 deletions packages/api/src/ticketing/collection/services/github/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ICollectionMapper } from '@ticketing/collection/types';
import { GithubCollectionInput, GithubCollectionOutput } from './types';
import {
UnifiedCollectionInput,
UnifiedCollectionOutput,
} from '@ticketing/collection/types/model.unified';
import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
import { Injectable } from '@nestjs/common';
import { Utils } from '@ticketing/@lib/@utils';

@Injectable()
export class GithubCollectionMapper implements ICollectionMapper {
constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
this.mappersRegistry.registerService(
'ticketing',
'collection',
'github',
this,
);
}
desunify(
source: UnifiedCollectionInput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): GithubCollectionInput {
return;
}

unify(
source: GithubCollectionOutput | GithubCollectionOutput[],
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedCollectionOutput | UnifiedCollectionOutput[] {
// If the source is not an array, convert it to an array for mapping
const sourcesArray = Array.isArray(source) ? source : [source];

return sourcesArray.map((collection) =>
this.mapSingleCollectionToUnified(
collection,
connectionId,
customFieldMappings,
),
);
}

private mapSingleCollectionToUnified(
collection: GithubCollectionOutput,
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedCollectionOutput {
const unifiedCollection: UnifiedCollectionOutput = {
remote_id: String(collection.id),
remote_data: collection,
name: collection.name,
description: collection.description,
collection_type: 'PROJECT',
};

return unifiedCollection;
}
}
127 changes: 127 additions & 0 deletions packages/api/src/ticketing/collection/services/github/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
interface GithubCollection {
id: number
node_id: string
name: string
full_name: string
owner: Owner
private: boolean
html_url: string
description: string
fork: boolean
url: string
archive_url: string
assignees_url: string
blobs_url: string
branches_url: string
collaborators_url: string
comments_url: string
commits_url: string
compare_url: string
contents_url: string
contributors_url: string
deployments_url: string
downloads_url: string
events_url: string
forks_url: string
git_commits_url: string
git_refs_url: string
git_tags_url: string
git_url: string
issue_comment_url: string
issue_events_url: string
issues_url: string
keys_url: string
labels_url: string
languages_url: string
merges_url: string
milestones_url: string
notifications_url: string
pulls_url: string
releases_url: string
ssh_url: string
stargazers_url: string
statuses_url: string
subscribers_url: string
subscription_url: string
tags_url: string
teams_url: string
trees_url: string
clone_url: string
mirror_url: string
hooks_url: string
svn_url: string
homepage: string
language: any
forks_count: number
stargazers_count: number
watchers_count: number
size: number
default_branch: string
open_issues_count: number
is_template: boolean
topics: string[]
has_issues: boolean
has_projects: boolean
has_wiki: boolean
has_pages: boolean
has_downloads: boolean
archived: boolean
disabled: boolean
visibility: string
pushed_at: string
created_at: string
updated_at: string
permissions: Permissions
allow_rebase_merge: boolean
template_repository: any
temp_clone_token: string
allow_squash_merge: boolean
allow_auto_merge: boolean
delete_branch_on_merge: boolean
allow_merge_commit: boolean
subscribers_count: number
network_count: number
license: License
forks: number
open_issues: number
watchers: number
}

interface Owner {
login: string
id: number
node_id: string
avatar_url: string
gravatar_id: string
url: string
html_url: string
followers_url: string
following_url: string
gists_url: string
starred_url: string
subscriptions_url: string
organizations_url: string
repos_url: string
events_url: string
received_events_url: string
type: string
site_admin: boolean
}

interface Permissions {
admin: boolean
push: boolean
pull: boolean
}

interface License {
key: string
name: string
url: string
spdx_id: string
node_id: string
html_url: string
}

export type GithubCollectionInput = Partial<GithubCollection>;
export type GithubCollectionOutput = GithubCollectionInput;
76 changes: 76 additions & 0 deletions packages/api/src/ticketing/tag/services/github/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Injectable } from '@nestjs/common';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { TicketingObject } from '@ticketing/@lib/@types';
import { ApiResponse } from '@@core/utils/types';
import axios from 'axios';
import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
import { ServiceRegistry } from '../registry.service';
import { ITagService } from '@ticketing/tag/types';
import { GithubTagOutput } from './types';
import { SyncParam } from '@@core/utils/types/interface';

@Injectable()
export class GithubService implements ITagService {
constructor(
private prisma: PrismaService,
private logger: LoggerService,
private cryptoService: EncryptionService,
private registry: ServiceRegistry,
) {
this.logger.setContext(
TicketingObject.tag.toUpperCase() + ':' + GithubService.name,
);
this.registry.registerService('github', this);
}

async sync(data: SyncParam): Promise<ApiResponse<GithubTagOutput[]>> {
try {
const { linkedUserId } = data;

const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'github',
vertical: 'ticketing',
},
});

const repos = await axios.get(`${connection.account_url}/user/repos`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
});
let resp: any = [];
for (const repo of repos.data) {
if (repo.id) {
const tags = await axios.get(
`${connection.account_url}/repos/${repo.owner.login}/${repo.name}/labels`,
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
},
);
resp = [...resp, tags.data];
}
}
this.logger.log(`Synced github tags !`);

return {
data: resp.flat(),
message: 'Github tags retrieved',
statusCode: 200,
};
} catch (error) {
throw error;
}
}
}
58 changes: 58 additions & 0 deletions packages/api/src/ticketing/tag/services/github/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ITagMapper } from '@ticketing/tag/types';
import { GithubTagInput, GithubTagOutput } from './types';
import {
UnifiedTagInput,
UnifiedTagOutput,
} from '@ticketing/tag/types/model.unified';
import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
import { Injectable } from '@nestjs/common';
import { Utils } from '@ticketing/@lib/@utils';

@Injectable()
export class GithubTagMapper implements ITagMapper {
constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
this.mappersRegistry.registerService('ticketing', 'tag', 'github', this);
}
desunify(
source: UnifiedTagInput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): GithubTagInput {
return;
}

unify(
source: GithubTagOutput | GithubTagOutput[],
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedTagOutput | UnifiedTagOutput[] {
// If the source is not an array, convert it to an array for mapping
const sourcesArray = Array.isArray(source) ? source : [source];

return sourcesArray.map((tag) =>
this.mapSingleTagToUnified(tag, connectionId, customFieldMappings),
);
}

private mapSingleTagToUnified(
tag: GithubTagOutput,
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedTagOutput {
const unifiedTag: UnifiedTagOutput = {
remote_id: tag.id ? String(tag.id) : null,
remote_data: tag,
name: tag.name,
};

return unifiedTag;
}
}
Loading

0 comments on commit ef976f7

Please sign in to comment.