Skip to content

Commit

Permalink
adding linear comment
Browse files Browse the repository at this point in the history
  • Loading branch information
ganimtron-10 committed Aug 8, 2024
1 parent 33e34ea commit 5c520ff
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LinearCommentInput, LinearCommentOutput } from '@ticketing/comment/services/linear/types';

import { LinearCollectionInput, LinearCollectionOutput } from '@ticketing/collection/services/linear/types';

import { LinearTagInput, LinearTagOutput } from '@ticketing/tag/services/linear/types';
Expand Down Expand Up @@ -149,7 +151,7 @@ export type OriginalCommentInput =
| FrontCommentInput
| GorgiasCommentInput
| JiraCommentInput
| GitlabCommentInput;
| GitlabCommentInput | LinearCommentInput;
//| JiraCommentServiceMgmtInput;
/* user */
export type OriginalUserInput =
Expand Down Expand Up @@ -214,7 +216,7 @@ export type OriginalCommentOutput =
| FrontCommentOutput
| GorgiasCommentOutput
| JiraCommentOutput
| GitlabCommentOutput;
| GitlabCommentOutput | LinearCommentOutput;
/* user */
export type OriginalUserOutput =
| ZendeskUserOutput
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/ticketing/comment/comment.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { LinearCommentMapper } from './services/linear/mappers';
import { LinearService } from './services/linear';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';

Expand Down Expand Up @@ -42,6 +44,8 @@ import { SyncService } from './sync/sync.service';
JiraCommentMapper,
GorgiasCommentMapper,
GitlabCommentMapper,
LinearService,
LinearCommentMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
Expand Down
118 changes: 118 additions & 0 deletions packages/api/src/ticketing/comment/services/linear/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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 { Injectable } from '@nestjs/common';
import { TicketingObject } from '@ticketing/@lib/@types';
import { Utils } from '@ticketing/@lib/@utils';
import { ICommentService } from '@ticketing/comment/types';
import axios from 'axios';
import * as fs from 'fs';
import { ServiceRegistry } from '../registry.service';
import { LinearCommentInput, LinearCommentOutput } from './types';
import { LinearTicketOutput } from '@ticketing/ticket/services/linear/types';

@Injectable()
export class LinearService implements ICommentService {
constructor(
private prisma: PrismaService,
private logger: LoggerService,
private cryptoService: EncryptionService,
private registry: ServiceRegistry,
private utils: Utils,
) {
this.logger.setContext(
TicketingObject.comment.toUpperCase() + ':' + LinearService.name,
);
this.registry.registerService('linear', this);
}

async addComment(
commentData: LinearCommentInput,
linkedUserId: string,
remoteIdTicket: string,
): Promise<ApiResponse<LinearCommentOutput>> {
try {
const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'linear',
vertical: 'ticketing',
},
});

// Skipping Storing the attachment in unified object as Linear stores attachment as link in Markdown Format

const createCommentMutation = {
"query": `mutation { commentCreate( input: { body: \"${commentData.body}\" issueId: \"${remoteIdTicket}\" } ) { comment { body issue { id } user { id } } }}`
};

let resp = await axios.post(
`${connection.account_url}`,
createCommentMutation, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
});


return {
data: resp.data.data.issueLabels.nodes,
message: 'Linear comment created',
statusCode: 201,
};
} catch (error) {
throw error;
}
}
async sync(data: SyncParam): Promise<ApiResponse<LinearCommentOutput[]>> {
try {
const { linkedUserId, id_ticket } = data;

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

const ticket = await this.prisma.tcg_tickets.findUnique({
where: {
id_tcg_ticket: id_ticket as string,
},
select: {
remote_id: true,
},
});

const commentQuery = {
"query": `query { issue(id: \"${ticket.remote_id}\") { comments { nodes { id body user { id } issue { id } } } }}`
};

let resp = await axios.post(
`${connection.account_url}`,
commentQuery, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
});
this.logger.log(`Synced linear comments !`);

return {
data: resp.data.data.issue.comments.nodes,
message: 'Linear comments retrieved',
statusCode: 200,
};
} catch (error) {
throw error;
}
}
}
99 changes: 99 additions & 0 deletions packages/api/src/ticketing/comment/services/linear/mappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { OriginalAttachmentOutput } from '@@core/utils/types/original/original.ticketing';
import { Injectable } from '@nestjs/common';
import { TicketingObject } from '@ticketing/@lib/@types';
import { Utils } from '@ticketing/@lib/@utils';
import { UnifiedTicketingAttachmentOutput } from '@ticketing/attachment/types/model.unified';
import { ICommentMapper } from '@ticketing/comment/types';
import {
UnifiedTicketingCommentInput,
UnifiedTicketingCommentOutput,
} from '@ticketing/comment/types/model.unified';
import { LinearCommentInput, LinearCommentOutput } from './types';

@Injectable()
export class LinearCommentMapper implements ICommentMapper {
constructor(
private mappersRegistry: MappersRegistry,
private utils: Utils,
private coreUnificationService: CoreUnification,
) {
this.mappersRegistry.registerService(
'ticketing',
'comment',
'linear',
this,
);
}

async desunify(
source: UnifiedTicketingCommentInput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<LinearCommentInput> {
// project_id and issue_id will be extracted and used so We do not need to set user (author) field here

// TODO - Add attachments attribute

const result: LinearCommentInput = {
body: source.body,
};
return result;
}

async unify(
source: LinearCommentOutput | LinearCommentOutput[],
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<UnifiedTicketingCommentOutput | UnifiedTicketingCommentOutput[]> {
if (!Array.isArray(source)) {
return await this.mapSingleCommentToUnified(
source,
connectionId,
customFieldMappings,
);
}
return Promise.all(
source.map((comment) =>
this.mapSingleCommentToUnified(
comment,
connectionId,
customFieldMappings,
),
),
);
}

private async mapSingleCommentToUnified(
comment: LinearCommentOutput,
connectionId: string,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): Promise<UnifiedTicketingCommentOutput> {
let user_id: string;

if (comment.user.id) {
user_id = await this.utils.getUserUuidFromRemoteId(
String(comment.user.id),
connectionId,
);
}

return {
remote_id: comment.id,
remote_data: comment,
body: comment.body || null,
ticket_id: comment.issue.id,
user_id: user_id,
creator_type: 'USER',
};
}
}
13 changes: 13 additions & 0 deletions packages/api/src/ticketing/comment/services/linear/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface LinearComment {
id: string
body: string
user: {
id: string
}
issue: {
id: string
}
}

export type LinearCommentInput = Partial<LinearComment>;
export type LinearCommentOutput = LinearCommentInput;

0 comments on commit 5c520ff

Please sign in to comment.