airbyte-faros-destination 0.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -0
- package/lib/common/write-stats.d.ts +16 -0
- package/lib/common/write-stats.js +48 -0
- package/lib/community/hasura-client.d.ts +27 -0
- package/lib/community/hasura-client.js +278 -0
- package/lib/community/hasura-writer.d.ts +12 -0
- package/lib/community/hasura-writer.js +44 -0
- package/lib/community/types.d.ts +26 -0
- package/lib/community/types.js +9 -0
- package/lib/converters/agileaccelerator/agileaccelerator_types.d.ts +315 -0
- package/lib/converters/agileaccelerator/agileaccelerator_types.js +81 -0
- package/lib/converters/agileaccelerator/common.d.ts +64 -0
- package/lib/converters/agileaccelerator/common.js +167 -0
- package/lib/converters/agileaccelerator/works.d.ts +7 -0
- package/lib/converters/agileaccelerator/works.js +105 -0
- package/lib/converters/asana/common.d.ts +39 -0
- package/lib/converters/asana/common.js +64 -0
- package/lib/converters/asana/projects.d.ts +7 -0
- package/lib/converters/asana/projects.js +29 -0
- package/lib/converters/asana/sections.d.ts +7 -0
- package/lib/converters/asana/sections.js +28 -0
- package/lib/converters/asana/stories.d.ts +7 -0
- package/lib/converters/asana/stories.js +32 -0
- package/lib/converters/asana/tags.d.ts +7 -0
- package/lib/converters/asana/tags.js +22 -0
- package/lib/converters/asana/tasks.d.ts +11 -0
- package/lib/converters/asana/tasks.js +160 -0
- package/lib/converters/asana/users.d.ts +7 -0
- package/lib/converters/asana/users.js +16 -0
- package/lib/converters/backlog/common.d.ts +20 -0
- package/lib/converters/backlog/common.js +59 -0
- package/lib/converters/backlog/issues.d.ts +7 -0
- package/lib/converters/backlog/issues.js +119 -0
- package/lib/converters/backlog/models.d.ts +156 -0
- package/lib/converters/backlog/models.js +23 -0
- package/lib/converters/backlog/projects.d.ts +7 -0
- package/lib/converters/backlog/projects.js +78 -0
- package/lib/converters/backlog/users.d.ts +7 -0
- package/lib/converters/backlog/users.js +26 -0
- package/lib/converters/bitbucket/branches.d.ts +7 -0
- package/lib/converters/bitbucket/branches.js +31 -0
- package/lib/converters/bitbucket/commits.d.ts +7 -0
- package/lib/converters/bitbucket/commits.js +50 -0
- package/lib/converters/bitbucket/common.d.ts +28 -0
- package/lib/converters/bitbucket/common.js +56 -0
- package/lib/converters/bitbucket/deployments.d.ts +11 -0
- package/lib/converters/bitbucket/deployments.js +100 -0
- package/lib/converters/bitbucket/issues.d.ts +12 -0
- package/lib/converters/bitbucket/issues.js +111 -0
- package/lib/converters/bitbucket/pipeline_steps.d.ts +10 -0
- package/lib/converters/bitbucket/pipeline_steps.js +83 -0
- package/lib/converters/bitbucket/pipelines.d.ts +8 -0
- package/lib/converters/bitbucket/pipelines.js +90 -0
- package/lib/converters/bitbucket/pull_request_activities.d.ts +13 -0
- package/lib/converters/bitbucket/pull_request_activities.js +112 -0
- package/lib/converters/bitbucket/pull_requests.d.ts +10 -0
- package/lib/converters/bitbucket/pull_requests.js +95 -0
- package/lib/converters/bitbucket/repositories.d.ts +9 -0
- package/lib/converters/bitbucket/repositories.js +41 -0
- package/lib/converters/bitbucket/types.d.ts +667 -0
- package/lib/converters/bitbucket/types.js +2 -0
- package/lib/converters/bitbucket/workspace_users.d.ts +7 -0
- package/lib/converters/bitbucket/workspace_users.js +31 -0
- package/lib/converters/bitbucket/workspaces.d.ts +8 -0
- package/lib/converters/bitbucket/workspaces.js +61 -0
- package/lib/converters/converter-registry.d.ts +25 -0
- package/lib/converters/converter-registry.js +64 -0
- package/lib/converters/converter.d.ts +63 -0
- package/lib/converters/converter.js +122 -0
- package/lib/converters/datadog/common.d.ts +27 -0
- package/lib/converters/datadog/common.js +34 -0
- package/lib/converters/datadog/incidents.d.ts +9 -0
- package/lib/converters/datadog/incidents.js +128 -0
- package/lib/converters/datadog/users.d.ts +7 -0
- package/lib/converters/datadog/users.js +27 -0
- package/lib/converters/docker/common.d.ts +87 -0
- package/lib/converters/docker/common.js +76 -0
- package/lib/converters/docker/tags.d.ts +8 -0
- package/lib/converters/docker/tags.js +98 -0
- package/lib/converters/github/assignees.d.ts +7 -0
- package/lib/converters/github/assignees.js +16 -0
- package/lib/converters/github/branches.d.ts +7 -0
- package/lib/converters/github/branches.js +28 -0
- package/lib/converters/github/collaborators.d.ts +7 -0
- package/lib/converters/github/collaborators.js +19 -0
- package/lib/converters/github/commits.d.ts +7 -0
- package/lib/converters/github/commits.js +48 -0
- package/lib/converters/github/common.d.ts +37 -0
- package/lib/converters/github/common.js +130 -0
- package/lib/converters/github/issue_labels.d.ts +7 -0
- package/lib/converters/github/issue_labels.js +20 -0
- package/lib/converters/github/issue_milestones.d.ts +8 -0
- package/lib/converters/github/issue_milestones.js +42 -0
- package/lib/converters/github/issues.d.ts +9 -0
- package/lib/converters/github/issues.js +90 -0
- package/lib/converters/github/organizations.d.ts +7 -0
- package/lib/converters/github/organizations.js +37 -0
- package/lib/converters/github/projects.d.ts +7 -0
- package/lib/converters/github/projects.js +21 -0
- package/lib/converters/github/pull_request_stats.d.ts +7 -0
- package/lib/converters/github/pull_request_stats.js +43 -0
- package/lib/converters/github/pull_requests.d.ts +7 -0
- package/lib/converters/github/pull_requests.js +63 -0
- package/lib/converters/github/releases.d.ts +7 -0
- package/lib/converters/github/releases.js +51 -0
- package/lib/converters/github/repositories.d.ts +7 -0
- package/lib/converters/github/repositories.js +44 -0
- package/lib/converters/github/review_comments.d.ts +7 -0
- package/lib/converters/github/review_comments.js +39 -0
- package/lib/converters/github/reviews.d.ts +7 -0
- package/lib/converters/github/reviews.js +58 -0
- package/lib/converters/github/tags.d.ts +7 -0
- package/lib/converters/github/tags.js +31 -0
- package/lib/converters/github/users.d.ts +7 -0
- package/lib/converters/github/users.js +19 -0
- package/lib/converters/gitlab/branches.d.ts +8 -0
- package/lib/converters/gitlab/branches.js +44 -0
- package/lib/converters/gitlab/commits.d.ts +7 -0
- package/lib/converters/gitlab/commits.js +33 -0
- package/lib/converters/gitlab/common.d.ts +30 -0
- package/lib/converters/gitlab/common.js +70 -0
- package/lib/converters/gitlab/group_labels.d.ts +7 -0
- package/lib/converters/gitlab/group_labels.js +15 -0
- package/lib/converters/gitlab/group_milestones.d.ts +8 -0
- package/lib/converters/gitlab/group_milestones.js +41 -0
- package/lib/converters/gitlab/groups.d.ts +7 -0
- package/lib/converters/gitlab/groups.js +43 -0
- package/lib/converters/gitlab/issues.d.ts +10 -0
- package/lib/converters/gitlab/issues.js +79 -0
- package/lib/converters/gitlab/jobs.d.ts +11 -0
- package/lib/converters/gitlab/jobs.js +75 -0
- package/lib/converters/gitlab/merge_request_commits.d.ts +7 -0
- package/lib/converters/gitlab/merge_request_commits.js +34 -0
- package/lib/converters/gitlab/merge_requests.d.ts +10 -0
- package/lib/converters/gitlab/merge_requests.js +65 -0
- package/lib/converters/gitlab/pipelines.d.ts +7 -0
- package/lib/converters/gitlab/pipelines.js +41 -0
- package/lib/converters/gitlab/project_labels.d.ts +7 -0
- package/lib/converters/gitlab/project_labels.js +15 -0
- package/lib/converters/gitlab/project_milestones.d.ts +8 -0
- package/lib/converters/gitlab/project_milestones.js +41 -0
- package/lib/converters/gitlab/projects.d.ts +7 -0
- package/lib/converters/gitlab/projects.js +51 -0
- package/lib/converters/gitlab/releases.d.ts +10 -0
- package/lib/converters/gitlab/releases.js +68 -0
- package/lib/converters/gitlab/tags.d.ts +10 -0
- package/lib/converters/gitlab/tags.js +41 -0
- package/lib/converters/gitlab/users.d.ts +7 -0
- package/lib/converters/gitlab/users.js +33 -0
- package/lib/converters/googlecalendar/calendar_models.d.ts +618 -0
- package/lib/converters/googlecalendar/calendar_models.js +2 -0
- package/lib/converters/googlecalendar/calendars.d.ts +7 -0
- package/lib/converters/googlecalendar/calendars.js +29 -0
- package/lib/converters/googlecalendar/common.d.ts +52 -0
- package/lib/converters/googlecalendar/common.js +130 -0
- package/lib/converters/googlecalendar/events.d.ts +8 -0
- package/lib/converters/googlecalendar/events.js +117 -0
- package/lib/converters/harness/common.d.ts +105 -0
- package/lib/converters/harness/common.js +16 -0
- package/lib/converters/harness/executions.d.ts +15 -0
- package/lib/converters/harness/executions.js +245 -0
- package/lib/converters/jenkins/builds.d.ts +9 -0
- package/lib/converters/jenkins/builds.js +74 -0
- package/lib/converters/jenkins/common.d.ts +25 -0
- package/lib/converters/jenkins/common.js +54 -0
- package/lib/converters/jenkins/jobs.d.ts +8 -0
- package/lib/converters/jenkins/jobs.js +29 -0
- package/lib/converters/jira/board_issues.d.ts +7 -0
- package/lib/converters/jira/board_issues.js +28 -0
- package/lib/converters/jira/boards.d.ts +7 -0
- package/lib/converters/jira/boards.js +34 -0
- package/lib/converters/jira/common.d.ts +61 -0
- package/lib/converters/jira/common.js +64 -0
- package/lib/converters/jira/epics.d.ts +8 -0
- package/lib/converters/jira/epics.js +45 -0
- package/lib/converters/jira/issue_fields.d.ts +7 -0
- package/lib/converters/jira/issue_fields.js +15 -0
- package/lib/converters/jira/issues.d.ts +52 -0
- package/lib/converters/jira/issues.js +545 -0
- package/lib/converters/jira/project_versions.d.ts +9 -0
- package/lib/converters/jira/project_versions.js +48 -0
- package/lib/converters/jira/projects.d.ts +7 -0
- package/lib/converters/jira/projects.js +40 -0
- package/lib/converters/jira/pull_requests.d.ts +7 -0
- package/lib/converters/jira/pull_requests.js +15 -0
- package/lib/converters/jira/sprint_issues.d.ts +7 -0
- package/lib/converters/jira/sprint_issues.js +15 -0
- package/lib/converters/jira/sprints.d.ts +16 -0
- package/lib/converters/jira/sprints.js +80 -0
- package/lib/converters/jira/users.d.ts +8 -0
- package/lib/converters/jira/users.js +33 -0
- package/lib/converters/jira/workflow_statuses.d.ts +7 -0
- package/lib/converters/jira/workflow_statuses.js +15 -0
- package/lib/converters/jsonata.d.ts +17 -0
- package/lib/converters/jsonata.js +47 -0
- package/lib/converters/okta/common.d.ts +8 -0
- package/lib/converters/okta/common.js +17 -0
- package/lib/converters/okta/groups.d.ts +7 -0
- package/lib/converters/okta/groups.js +47 -0
- package/lib/converters/okta/models.d.ts +102 -0
- package/lib/converters/okta/models.js +2 -0
- package/lib/converters/okta/users.d.ts +8 -0
- package/lib/converters/okta/users.js +73 -0
- package/lib/converters/okta_faros/common.d.ts +4 -0
- package/lib/converters/okta_faros/common.js +11 -0
- package/lib/converters/okta_faros/groups.d.ts +13 -0
- package/lib/converters/okta_faros/groups.js +23 -0
- package/lib/converters/okta_faros/users.d.ts +13 -0
- package/lib/converters/okta_faros/users.js +23 -0
- package/lib/converters/pagerduty/common.d.ts +37 -0
- package/lib/converters/pagerduty/common.js +40 -0
- package/lib/converters/pagerduty/incident_log_entries.d.ts +8 -0
- package/lib/converters/pagerduty/incident_log_entries.js +56 -0
- package/lib/converters/pagerduty/incidents.d.ts +10 -0
- package/lib/converters/pagerduty/incidents.js +127 -0
- package/lib/converters/pagerduty/priorities_resource.d.ts +11 -0
- package/lib/converters/pagerduty/priorities_resource.js +64 -0
- package/lib/converters/pagerduty/users.d.ts +7 -0
- package/lib/converters/pagerduty/users.js +26 -0
- package/lib/converters/phabricator/commits.d.ts +8 -0
- package/lib/converters/phabricator/commits.js +75 -0
- package/lib/converters/phabricator/common.d.ts +40 -0
- package/lib/converters/phabricator/common.js +107 -0
- package/lib/converters/phabricator/repositories.d.ts +7 -0
- package/lib/converters/phabricator/repositories.js +56 -0
- package/lib/converters/phabricator/revisions.d.ts +7 -0
- package/lib/converters/phabricator/revisions.js +83 -0
- package/lib/converters/phabricator/users.d.ts +7 -0
- package/lib/converters/phabricator/users.js +39 -0
- package/lib/converters/shortcut/common.d.ts +16 -0
- package/lib/converters/shortcut/common.js +68 -0
- package/lib/converters/shortcut/epics.d.ts +7 -0
- package/lib/converters/shortcut/epics.js +29 -0
- package/lib/converters/shortcut/iterations.d.ts +7 -0
- package/lib/converters/shortcut/iterations.js +29 -0
- package/lib/converters/shortcut/members.d.ts +7 -0
- package/lib/converters/shortcut/members.js +26 -0
- package/lib/converters/shortcut/models.d.ts +392 -0
- package/lib/converters/shortcut/models.js +30 -0
- package/lib/converters/shortcut/projects.d.ts +7 -0
- package/lib/converters/shortcut/projects.js +46 -0
- package/lib/converters/shortcut/stories.d.ts +7 -0
- package/lib/converters/shortcut/stories.js +127 -0
- package/lib/converters/squadcast/common.d.ts +169 -0
- package/lib/converters/squadcast/common.js +62 -0
- package/lib/converters/squadcast/events.d.ts +9 -0
- package/lib/converters/squadcast/events.js +53 -0
- package/lib/converters/squadcast/incidents.d.ts +10 -0
- package/lib/converters/squadcast/incidents.js +141 -0
- package/lib/converters/squadcast/services.d.ts +7 -0
- package/lib/converters/squadcast/services.js +28 -0
- package/lib/converters/squadcast/users.d.ts +7 -0
- package/lib/converters/squadcast/users.js +27 -0
- package/lib/converters/statuspage/common.d.ts +93 -0
- package/lib/converters/statuspage/common.js +80 -0
- package/lib/converters/statuspage/incident_updates.d.ts +8 -0
- package/lib/converters/statuspage/incident_updates.js +45 -0
- package/lib/converters/statuspage/incidents.d.ts +10 -0
- package/lib/converters/statuspage/incidents.js +128 -0
- package/lib/converters/statuspage/users.d.ts +7 -0
- package/lib/converters/statuspage/users.js +26 -0
- package/lib/converters/victorops/common.d.ts +16 -0
- package/lib/converters/victorops/common.js +24 -0
- package/lib/converters/victorops/incidents.d.ts +12 -0
- package/lib/converters/victorops/incidents.js +209 -0
- package/lib/converters/victorops/teams.d.ts +8 -0
- package/lib/converters/victorops/teams.js +30 -0
- package/lib/converters/victorops/users.d.ts +8 -0
- package/lib/converters/victorops/users.js +33 -0
- package/lib/destination-runner.d.ts +12 -0
- package/lib/destination-runner.js +22 -0
- package/lib/destination.d.ts +42 -0
- package/lib/destination.js +508 -0
- package/lib/index.d.ts +16 -0
- package/lib/index.js +39 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +71 -0
- package/resources/fetch-primary-keys.sql +16 -0
- package/resources/introspection-query.gql +61 -0
- package/resources/spec.json +468 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Epics = void 0;
|
|
7
|
+
const turndown_1 = __importDefault(require("turndown"));
|
|
8
|
+
const common_1 = require("./common");
|
|
9
|
+
class Epics extends common_1.JiraConverter {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.destinationModels = ['tms_Epic'];
|
|
13
|
+
this.turndown = new turndown_1.default();
|
|
14
|
+
}
|
|
15
|
+
async convert(record, ctx) {
|
|
16
|
+
var _a, _b, _c;
|
|
17
|
+
const epic = record.record.data;
|
|
18
|
+
const source = this.streamName.source;
|
|
19
|
+
const status = (_a = epic.fields.status) !== null && _a !== void 0 ? _a : {};
|
|
20
|
+
let description = null;
|
|
21
|
+
if (typeof epic.fields.description === 'string') {
|
|
22
|
+
description = epic.fields.description;
|
|
23
|
+
}
|
|
24
|
+
else if (epic.renderedFields.description) {
|
|
25
|
+
description = this.turndown.turndown(epic.renderedFields.description);
|
|
26
|
+
}
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
model: 'tms_Epic',
|
|
30
|
+
record: {
|
|
31
|
+
uid: epic.key,
|
|
32
|
+
name: (_b = epic.fields.summary) !== null && _b !== void 0 ? _b : null,
|
|
33
|
+
description: this.truncate(ctx, description),
|
|
34
|
+
status: {
|
|
35
|
+
category: common_1.JiraStatusCategories.get(common_1.JiraCommon.normalize((_c = status.statusCategory) === null || _c === void 0 ? void 0 : _c.name)),
|
|
36
|
+
detail: status.name,
|
|
37
|
+
},
|
|
38
|
+
project: { uid: epic.projectKey, source },
|
|
39
|
+
source,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.Epics = Epics;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AirbyteRecord } from 'faros-airbyte-cdk';
|
|
2
|
+
import { DestinationModel, DestinationRecord, StreamContext } from '../converter';
|
|
3
|
+
import { JiraConverter } from './common';
|
|
4
|
+
export declare class IssueFields extends JiraConverter {
|
|
5
|
+
readonly destinationModels: ReadonlyArray<DestinationModel>;
|
|
6
|
+
convert(record: AirbyteRecord, ctx: StreamContext): Promise<ReadonlyArray<DestinationRecord>>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IssueFields = void 0;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
// Required as dependency by Issues and Sprints stream
|
|
6
|
+
class IssueFields extends common_1.JiraConverter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.destinationModels = [];
|
|
10
|
+
}
|
|
11
|
+
async convert(record, ctx) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.IssueFields = IssueFields;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AirbyteRecord } from 'faros-airbyte-cdk';
|
|
2
|
+
import { DestinationModel, DestinationRecord, StreamContext, StreamName } from '../converter';
|
|
3
|
+
import { JiraConverter } from './common';
|
|
4
|
+
export declare class Issues extends JiraConverter {
|
|
5
|
+
private logger;
|
|
6
|
+
readonly destinationModels: ReadonlyArray<DestinationModel>;
|
|
7
|
+
private static readonly issueFieldsStream;
|
|
8
|
+
private static readonly pullRequestsStream;
|
|
9
|
+
private static readonly workflowStatusesStream;
|
|
10
|
+
private static readonly standardFieldIds;
|
|
11
|
+
private static readonly fieldsToIgnore;
|
|
12
|
+
private fieldIdsByName?;
|
|
13
|
+
private fieldNameById?;
|
|
14
|
+
private statusByName?;
|
|
15
|
+
private turndown;
|
|
16
|
+
get dependencies(): ReadonlyArray<StreamName>;
|
|
17
|
+
private static getFieldIdsByName;
|
|
18
|
+
private static getFieldNamesById;
|
|
19
|
+
private static getStatusesByName;
|
|
20
|
+
private static fieldChangelog;
|
|
21
|
+
private static assigneeChangelog;
|
|
22
|
+
private statusChangelog;
|
|
23
|
+
private getIssueEpic;
|
|
24
|
+
private getSprintId;
|
|
25
|
+
private getPoints;
|
|
26
|
+
private static extractRepo;
|
|
27
|
+
/**
|
|
28
|
+
* Attempts to retrieve a field's value from several typical locations within
|
|
29
|
+
* the field's JSON blob. If the blob is an array, then each item's value will
|
|
30
|
+
* be added to an array of strings which will be an entry in the returned
|
|
31
|
+
* object. Also each item in the array will be exploded across the returned
|
|
32
|
+
* object with the key '<name>_<index>'. If nothing can be done, then
|
|
33
|
+
* the JSON blob is set to the additional field's value after being stringified.
|
|
34
|
+
*
|
|
35
|
+
* @param name The name of the additional field
|
|
36
|
+
* @param jsonValue The field's JSON blob to retrieve the value from
|
|
37
|
+
* @return The Record of additional fields
|
|
38
|
+
*/
|
|
39
|
+
private retrieveAdditionalFieldValue;
|
|
40
|
+
/**
|
|
41
|
+
* Check for existence of the members 'value', 'name' and then
|
|
42
|
+
* 'displayName'in that order and return when one is found
|
|
43
|
+
* (or undefined if none).
|
|
44
|
+
*
|
|
45
|
+
* @param jsonValue The object whose members should be considered
|
|
46
|
+
* @returns The value, name or displayName within the object
|
|
47
|
+
*/
|
|
48
|
+
private retrieveFieldValue;
|
|
49
|
+
private getPullRequests;
|
|
50
|
+
private stringifyNonString;
|
|
51
|
+
convert(record: AirbyteRecord, ctx: StreamContext): Promise<ReadonlyArray<DestinationRecord>>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Issues = void 0;
|
|
7
|
+
const faros_airbyte_cdk_1 = require("faros-airbyte-cdk");
|
|
8
|
+
const faros_feeds_sdk_1 = require("faros-feeds-sdk");
|
|
9
|
+
const git_url_parse_1 = __importDefault(require("git-url-parse"));
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
const turndown_1 = __importDefault(require("turndown"));
|
|
12
|
+
const converter_1 = require("../converter");
|
|
13
|
+
const common_1 = require("./common");
|
|
14
|
+
const dependencyRegex = /((is (?<type>\w+))|tested) by/;
|
|
15
|
+
const sprintRegex = /([\w]+)=([\w-:. ]+)/g;
|
|
16
|
+
const statusCategories = new Map(['Todo', 'InProgress', 'Done'].map((s) => [common_1.JiraCommon.normalize(s), s]));
|
|
17
|
+
const typeCategories = new Map(['Bug', 'Story', 'Task'].map((t) => [common_1.JiraCommon.normalize(t), t]));
|
|
18
|
+
class Issues extends common_1.JiraConverter {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this.logger = new faros_airbyte_cdk_1.AirbyteLogger();
|
|
22
|
+
this.destinationModels = [
|
|
23
|
+
'tms_Task',
|
|
24
|
+
'tms_TaskProjectRelationship',
|
|
25
|
+
'tms_TaskReleaseRelationship',
|
|
26
|
+
'tms_TaskBoardRelationship',
|
|
27
|
+
'tms_TaskAssignment',
|
|
28
|
+
'tms_TaskDependency',
|
|
29
|
+
'tms_TaskTag',
|
|
30
|
+
'tms_TaskPullRequestAssociation',
|
|
31
|
+
];
|
|
32
|
+
this.turndown = new turndown_1.default();
|
|
33
|
+
}
|
|
34
|
+
get dependencies() {
|
|
35
|
+
return [
|
|
36
|
+
Issues.issueFieldsStream,
|
|
37
|
+
Issues.pullRequestsStream,
|
|
38
|
+
Issues.workflowStatusesStream,
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
static getFieldIdsByName(ctx) {
|
|
42
|
+
const records = ctx.getAll(Issues.issueFieldsStream.asString);
|
|
43
|
+
return (0, lodash_1.invertBy)((0, lodash_1.mapValues)(records, (r) => r.record.data.name));
|
|
44
|
+
}
|
|
45
|
+
static getFieldNamesById(ctx) {
|
|
46
|
+
const records = ctx.getAll(Issues.issueFieldsStream.asString);
|
|
47
|
+
return (0, lodash_1.mapValues)(records, (r) => r.record.data.name);
|
|
48
|
+
}
|
|
49
|
+
static getStatusesByName(ctx) {
|
|
50
|
+
const records = ctx.getAll(Issues.workflowStatusesStream.asString);
|
|
51
|
+
return (0, lodash_1.keyBy)(Object.values(records).map((r) => {
|
|
52
|
+
const data = r.record.data;
|
|
53
|
+
return {
|
|
54
|
+
detail: data.name,
|
|
55
|
+
category: data.statusCategory.name,
|
|
56
|
+
};
|
|
57
|
+
}), (s) => s.detail);
|
|
58
|
+
}
|
|
59
|
+
static fieldChangelog(changelog, field, fromField = 'fromString', valueField = 'toString') {
|
|
60
|
+
const fieldChangelog = [];
|
|
61
|
+
// Changelog entries are sorted from most to least recent
|
|
62
|
+
for (const change of changelog) {
|
|
63
|
+
for (const item of change.items) {
|
|
64
|
+
if (item.field === field) {
|
|
65
|
+
const changed = faros_feeds_sdk_1.Utils.toDate(change.created);
|
|
66
|
+
if (!changed) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
fieldChangelog.push({
|
|
70
|
+
from: item[fromField],
|
|
71
|
+
field,
|
|
72
|
+
value: item[valueField],
|
|
73
|
+
changed,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return fieldChangelog;
|
|
79
|
+
}
|
|
80
|
+
static assigneeChangelog(changelog, currentAssignee, created) {
|
|
81
|
+
const assigneeChangelog = [];
|
|
82
|
+
const assigneeChanges = Issues.fieldChangelog(changelog, 'assignee', 'from', 'to');
|
|
83
|
+
if (assigneeChanges.length) {
|
|
84
|
+
// case where task was already assigned at creation
|
|
85
|
+
const firstChange = assigneeChanges[0];
|
|
86
|
+
if (firstChange.from) {
|
|
87
|
+
const assignee = { uid: firstChange.from, assignedAt: created };
|
|
88
|
+
assigneeChangelog.push(assignee);
|
|
89
|
+
}
|
|
90
|
+
for (const change of assigneeChanges) {
|
|
91
|
+
const assignee = { uid: change.value, assignedAt: change.changed };
|
|
92
|
+
assigneeChangelog.push(assignee);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (currentAssignee) {
|
|
96
|
+
// if task was assigned at creation and never changed
|
|
97
|
+
assigneeChangelog.push({ uid: currentAssignee, assignedAt: created });
|
|
98
|
+
}
|
|
99
|
+
return assigneeChangelog;
|
|
100
|
+
}
|
|
101
|
+
statusChangelog(changelog, currentStatus, created) {
|
|
102
|
+
const statusChangelog = [];
|
|
103
|
+
const pushStatusChange = (statusName, date) => {
|
|
104
|
+
const status = this.statusByName[statusName];
|
|
105
|
+
if (status)
|
|
106
|
+
statusChangelog.push({ status, changedAt: date });
|
|
107
|
+
};
|
|
108
|
+
const statusChanges = Issues.fieldChangelog(changelog, 'status');
|
|
109
|
+
if (statusChanges.length) {
|
|
110
|
+
// status that was assigned at creation
|
|
111
|
+
const firstChange = statusChanges[0];
|
|
112
|
+
if (firstChange.from) {
|
|
113
|
+
pushStatusChange(firstChange.from, created);
|
|
114
|
+
}
|
|
115
|
+
for (const change of statusChanges) {
|
|
116
|
+
pushStatusChange(change.value, change.changed);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else if (currentStatus) {
|
|
120
|
+
// if task was given status at creation and never changed
|
|
121
|
+
pushStatusChange(currentStatus, created);
|
|
122
|
+
}
|
|
123
|
+
return statusChangelog;
|
|
124
|
+
}
|
|
125
|
+
getIssueEpic(issue) {
|
|
126
|
+
var _a, _b;
|
|
127
|
+
for (const id of (_a = this.fieldIdsByName[common_1.JiraCommon.EPIC_LINK_FIELD_NAME]) !== null && _a !== void 0 ? _a : []) {
|
|
128
|
+
const epic = issue.fields[id];
|
|
129
|
+
if (epic) {
|
|
130
|
+
return epic.toString();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (((_b = issue.fields.issuetype) === null || _b === void 0 ? void 0 : _b.name) === common_1.JiraCommon.EPIC_TYPE_NAME) {
|
|
134
|
+
return issue['key'];
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
getSprintId(issue) {
|
|
139
|
+
var _a, _b, _c, _d;
|
|
140
|
+
const sprints = [];
|
|
141
|
+
for (const fieldId of (_a = this.fieldIdsByName[common_1.JiraCommon.SPRINT_FIELD_NAME]) !== null && _a !== void 0 ? _a : []) {
|
|
142
|
+
for (const sprint of (_b = issue.fields[fieldId]) !== null && _b !== void 0 ? _b : []) {
|
|
143
|
+
// Workaround for string representation of sprint details which are supposedly deprecated
|
|
144
|
+
// https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-tostring-representation-of-sprints-in-get-issue-response/
|
|
145
|
+
if (typeof sprint === 'string') {
|
|
146
|
+
let match;
|
|
147
|
+
const details = {};
|
|
148
|
+
while ((match = sprintRegex.exec(sprint)) !== null) {
|
|
149
|
+
details[match[1]] = match[2];
|
|
150
|
+
}
|
|
151
|
+
sprints.push(details);
|
|
152
|
+
}
|
|
153
|
+
else if ((0, lodash_1.isPlainObject)(sprint)) {
|
|
154
|
+
sprints.push({
|
|
155
|
+
id: (_c = sprint.id) === null || _c === void 0 ? void 0 : _c.toString(),
|
|
156
|
+
state: sprint.state,
|
|
157
|
+
startDate: sprint.startDate,
|
|
158
|
+
endDate: sprint.endDate,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Sort array in descending order of end date sprints and return the first
|
|
164
|
+
// one. Future sprints may not have end dates but will take precedence.
|
|
165
|
+
sprints.sort(function (l, r) {
|
|
166
|
+
const lDate = faros_feeds_sdk_1.Utils.toDate(l.endDate);
|
|
167
|
+
const rDate = faros_feeds_sdk_1.Utils.toDate(r.endDate);
|
|
168
|
+
if (rDate && lDate) {
|
|
169
|
+
return rDate.getTime() - lDate.getTime();
|
|
170
|
+
}
|
|
171
|
+
else if ((0, lodash_1.toLower)(l.state) === 'future') {
|
|
172
|
+
return -1;
|
|
173
|
+
}
|
|
174
|
+
return 1;
|
|
175
|
+
});
|
|
176
|
+
return (_d = sprints[0]) === null || _d === void 0 ? void 0 : _d.id;
|
|
177
|
+
}
|
|
178
|
+
getPoints(issue) {
|
|
179
|
+
var _a;
|
|
180
|
+
for (const fieldName of common_1.JiraCommon.POINTS_FIELD_NAMES) {
|
|
181
|
+
const fieldIds = (_a = this.fieldIdsByName[fieldName]) !== null && _a !== void 0 ? _a : [];
|
|
182
|
+
for (const fieldId of fieldIds) {
|
|
183
|
+
const pointsString = issue.fields[fieldId];
|
|
184
|
+
if (!pointsString)
|
|
185
|
+
continue;
|
|
186
|
+
let points;
|
|
187
|
+
try {
|
|
188
|
+
points = faros_feeds_sdk_1.Utils.parseFloatFixedPoint(pointsString);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
this.logger.warn(`Failed to get story points for issue ${issue.key}: ${err.message}`);
|
|
192
|
+
}
|
|
193
|
+
return points;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
static extractRepo(repoUrl) {
|
|
199
|
+
var _a;
|
|
200
|
+
const gitUrl = (0, git_url_parse_1.default)(repoUrl);
|
|
201
|
+
const lowerSource = (_a = gitUrl.source) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
202
|
+
let source;
|
|
203
|
+
if (lowerSource === null || lowerSource === void 0 ? void 0 : lowerSource.includes('bitbucket'))
|
|
204
|
+
source = common_1.RepoSource.BITBUCKET;
|
|
205
|
+
else if (lowerSource === null || lowerSource === void 0 ? void 0 : lowerSource.includes('gitlab'))
|
|
206
|
+
source = common_1.RepoSource.GITLAB;
|
|
207
|
+
else if (lowerSource === null || lowerSource === void 0 ? void 0 : lowerSource.includes('github'))
|
|
208
|
+
source = common_1.RepoSource.GITHUB;
|
|
209
|
+
else
|
|
210
|
+
source = common_1.RepoSource.VCS;
|
|
211
|
+
return {
|
|
212
|
+
source,
|
|
213
|
+
org: gitUrl.organization,
|
|
214
|
+
name: gitUrl.name,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Attempts to retrieve a field's value from several typical locations within
|
|
219
|
+
* the field's JSON blob. If the blob is an array, then each item's value will
|
|
220
|
+
* be added to an array of strings which will be an entry in the returned
|
|
221
|
+
* object. Also each item in the array will be exploded across the returned
|
|
222
|
+
* object with the key '<name>_<index>'. If nothing can be done, then
|
|
223
|
+
* the JSON blob is set to the additional field's value after being stringified.
|
|
224
|
+
*
|
|
225
|
+
* @param name The name of the additional field
|
|
226
|
+
* @param jsonValue The field's JSON blob to retrieve the value from
|
|
227
|
+
* @return The Record of additional fields
|
|
228
|
+
*/
|
|
229
|
+
retrieveAdditionalFieldValue(ctx, name, jsonValue) {
|
|
230
|
+
const additionalFields = {};
|
|
231
|
+
if (!jsonValue || (0, lodash_1.isString)(jsonValue)) {
|
|
232
|
+
additionalFields[name] = jsonValue;
|
|
233
|
+
return additionalFields;
|
|
234
|
+
}
|
|
235
|
+
const retrievedValue = this.retrieveFieldValue(jsonValue);
|
|
236
|
+
if (retrievedValue) {
|
|
237
|
+
additionalFields[name] = this.stringifyNonString(retrievedValue);
|
|
238
|
+
return additionalFields;
|
|
239
|
+
}
|
|
240
|
+
if (Array.isArray(jsonValue)) {
|
|
241
|
+
// Truncate the array to the array limit
|
|
242
|
+
const inputArray = jsonValue.slice(0, this.additionalFieldsArrayLimit(ctx));
|
|
243
|
+
const resultArray = inputArray.map((item, index) => {
|
|
244
|
+
var _a;
|
|
245
|
+
const val = (_a = this.retrieveFieldValue(item)) !== null && _a !== void 0 ? _a : item;
|
|
246
|
+
// Also explode each item across additional fields
|
|
247
|
+
additionalFields[name + '_' + index] = this.stringifyNonString(val);
|
|
248
|
+
return val;
|
|
249
|
+
});
|
|
250
|
+
additionalFields[name] = JSON.stringify(resultArray);
|
|
251
|
+
return additionalFields;
|
|
252
|
+
}
|
|
253
|
+
// Nothing could be retrieved
|
|
254
|
+
additionalFields[name] = this.stringifyNonString(jsonValue);
|
|
255
|
+
return additionalFields;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Check for existence of the members 'value', 'name' and then
|
|
259
|
+
* 'displayName'in that order and return when one is found
|
|
260
|
+
* (or undefined if none).
|
|
261
|
+
*
|
|
262
|
+
* @param jsonValue The object whose members should be considered
|
|
263
|
+
* @returns The value, name or displayName within the object
|
|
264
|
+
*/
|
|
265
|
+
retrieveFieldValue(jsonValue) {
|
|
266
|
+
let val;
|
|
267
|
+
if (jsonValue === null || jsonValue === void 0 ? void 0 : jsonValue.value) {
|
|
268
|
+
val = jsonValue.value;
|
|
269
|
+
}
|
|
270
|
+
else if (jsonValue === null || jsonValue === void 0 ? void 0 : jsonValue.name) {
|
|
271
|
+
val = jsonValue.name;
|
|
272
|
+
}
|
|
273
|
+
else if (jsonValue === null || jsonValue === void 0 ? void 0 : jsonValue.displayName) {
|
|
274
|
+
val = jsonValue.displayName;
|
|
275
|
+
}
|
|
276
|
+
return val;
|
|
277
|
+
}
|
|
278
|
+
getPullRequests(ctx, issueId) {
|
|
279
|
+
var _a, _b, _c;
|
|
280
|
+
const pulls = [];
|
|
281
|
+
const record = ctx.get(Issues.pullRequestsStream.asString, issueId);
|
|
282
|
+
if (!record)
|
|
283
|
+
return pulls;
|
|
284
|
+
const detail = record.record.data;
|
|
285
|
+
try {
|
|
286
|
+
const branchToRepoUrl = new Map();
|
|
287
|
+
for (const branch of (_a = detail.branches) !== null && _a !== void 0 ? _a : []) {
|
|
288
|
+
branchToRepoUrl.set(branch.url, branch.repository.url);
|
|
289
|
+
}
|
|
290
|
+
for (const pull of (_b = detail.pullRequests) !== null && _b !== void 0 ? _b : []) {
|
|
291
|
+
const repoUrl = branchToRepoUrl.get((_c = pull.source) === null || _c === void 0 ? void 0 : _c.url);
|
|
292
|
+
if (!repoUrl) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
pulls.push({
|
|
296
|
+
repo: Issues.extractRepo(repoUrl),
|
|
297
|
+
number: faros_feeds_sdk_1.Utils.parseInteger(pull.id.replace('#', '')),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
this.logger.warn(`Failed to get pull requests for issue ${issueId}: ${err.message}`);
|
|
303
|
+
}
|
|
304
|
+
return pulls;
|
|
305
|
+
}
|
|
306
|
+
stringifyNonString(value) {
|
|
307
|
+
return (0, lodash_1.isString)(value) ? value : JSON.stringify(value);
|
|
308
|
+
}
|
|
309
|
+
async convert(record, ctx) {
|
|
310
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
311
|
+
const issue = record.record.data;
|
|
312
|
+
const source = this.streamName.source;
|
|
313
|
+
const results = [];
|
|
314
|
+
if (!this.fieldIdsByName) {
|
|
315
|
+
this.fieldIdsByName = Issues.getFieldIdsByName(ctx);
|
|
316
|
+
}
|
|
317
|
+
if (!this.fieldNameById) {
|
|
318
|
+
this.fieldNameById = Issues.getFieldNamesById(ctx);
|
|
319
|
+
}
|
|
320
|
+
if (!this.statusByName) {
|
|
321
|
+
this.statusByName = Issues.getStatusesByName(ctx);
|
|
322
|
+
}
|
|
323
|
+
results.push({
|
|
324
|
+
model: 'tms_TaskProjectRelationship',
|
|
325
|
+
record: {
|
|
326
|
+
task: { uid: issue.key, source },
|
|
327
|
+
project: { uid: issue.projectKey, source },
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
if (!this.useBoardOwnership(ctx)) {
|
|
331
|
+
results.push({
|
|
332
|
+
model: 'tms_TaskBoardRelationship',
|
|
333
|
+
record: {
|
|
334
|
+
task: { uid: issue.key, source },
|
|
335
|
+
board: { uid: issue.projectKey, source },
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
for (const label of issue.fields.labels) {
|
|
340
|
+
results.push({
|
|
341
|
+
model: 'tms_TaskTag',
|
|
342
|
+
record: { label: { name: label }, task: { uid: issue.key, source } },
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const pulls = this.getPullRequests(ctx, issue.id);
|
|
346
|
+
for (const pull of pulls) {
|
|
347
|
+
results.push({
|
|
348
|
+
model: 'tms_TaskPullRequestAssociation',
|
|
349
|
+
record: {
|
|
350
|
+
task: { uid: issue.key, source },
|
|
351
|
+
pullRequest: {
|
|
352
|
+
repository: {
|
|
353
|
+
organization: {
|
|
354
|
+
source: pull.repo.source,
|
|
355
|
+
uid: (0, lodash_1.toLower)(pull.repo.org),
|
|
356
|
+
},
|
|
357
|
+
name: (0, lodash_1.toLower)(pull.repo.name),
|
|
358
|
+
uid: (0, lodash_1.toLower)(pull.repo.name),
|
|
359
|
+
},
|
|
360
|
+
number: pull.number,
|
|
361
|
+
uid: pull.number.toString(),
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
const created = faros_feeds_sdk_1.Utils.toDate(issue.fields.created);
|
|
367
|
+
const assignee = ((_a = issue.fields.assignee) === null || _a === void 0 ? void 0 : _a.accountId) || ((_b = issue.fields.assignee) === null || _b === void 0 ? void 0 : _b.name);
|
|
368
|
+
const changelog = ((_c = issue.changelog) === null || _c === void 0 ? void 0 : _c.histories) || [];
|
|
369
|
+
changelog.sort((e1, e2) => {
|
|
370
|
+
// Sort changes from least to most recent
|
|
371
|
+
const created1 = +(faros_feeds_sdk_1.Utils.toDate(e1.created) || new Date(0));
|
|
372
|
+
const created2 = +(faros_feeds_sdk_1.Utils.toDate(e2.created) || new Date(0));
|
|
373
|
+
return created1 - created2;
|
|
374
|
+
});
|
|
375
|
+
const assigneeChangelog = Issues.assigneeChangelog(changelog, assignee, created);
|
|
376
|
+
for (const assignee of assigneeChangelog) {
|
|
377
|
+
results.push({
|
|
378
|
+
model: 'tms_TaskAssignment',
|
|
379
|
+
record: {
|
|
380
|
+
task: { uid: issue.key, source },
|
|
381
|
+
assignee: { uid: assignee.uid || 'Unassigned', source },
|
|
382
|
+
assignedAt: assignee.assignedAt,
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
const fixVersionChangelog = Issues.fieldChangelog(changelog, 'Fix Version', 'from', 'to');
|
|
387
|
+
for (const change of fixVersionChangelog) {
|
|
388
|
+
if (change.from) {
|
|
389
|
+
results.push({
|
|
390
|
+
model: 'tms_TaskReleaseRelationship__Deletion',
|
|
391
|
+
record: {
|
|
392
|
+
at: change.changed.getTime(),
|
|
393
|
+
where: {
|
|
394
|
+
task: { uid: issue.key, source },
|
|
395
|
+
release: { uid: change.from, source },
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
if (change.value) {
|
|
401
|
+
results.push({
|
|
402
|
+
model: 'tms_TaskReleaseRelationship__Upsert',
|
|
403
|
+
record: {
|
|
404
|
+
at: change.changed.getTime(),
|
|
405
|
+
data: {
|
|
406
|
+
task: { uid: issue.key, source },
|
|
407
|
+
release: { uid: change.value, source },
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
for (const fixVersion of (_d = issue.fields.fixVersions) !== null && _d !== void 0 ? _d : []) {
|
|
414
|
+
results.push({
|
|
415
|
+
model: 'tms_TaskReleaseRelationship__Upsert',
|
|
416
|
+
record: {
|
|
417
|
+
at: record.record.emitted_at,
|
|
418
|
+
data: {
|
|
419
|
+
task: { uid: issue.key, source },
|
|
420
|
+
release: { uid: fixVersion.id, source },
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const statusChangelog = this.statusChangelog(changelog, (_e = issue.fields.status) === null || _e === void 0 ? void 0 : _e.name, created);
|
|
426
|
+
// Timestamp of most recent status change
|
|
427
|
+
let statusChanged;
|
|
428
|
+
if (statusChangelog.length) {
|
|
429
|
+
statusChanged = statusChangelog[statusChangelog.length - 1].changedAt;
|
|
430
|
+
}
|
|
431
|
+
for (const link of (_f = issue.fields.issuelinks) !== null && _f !== void 0 ? _f : []) {
|
|
432
|
+
const match = (_g = link.type.inward) === null || _g === void 0 ? void 0 : _g.match(dependencyRegex);
|
|
433
|
+
const dependency = (_h = link.inwardIssue) === null || _h === void 0 ? void 0 : _h.key;
|
|
434
|
+
if (match && dependency) {
|
|
435
|
+
const blocking = match.groups.type === 'blocked';
|
|
436
|
+
results.push({
|
|
437
|
+
model: 'tms_TaskDependency',
|
|
438
|
+
record: {
|
|
439
|
+
dependentTask: { uid: issue.key, source },
|
|
440
|
+
fulfillingTask: { uid: dependency, source },
|
|
441
|
+
blocking,
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// Rewrite keys of additional fields to use names instead of ids
|
|
447
|
+
let additionalFieldsMap = {};
|
|
448
|
+
for (const [id, name] of Object.entries(this.fieldNameById)) {
|
|
449
|
+
const value = issue.fields[id];
|
|
450
|
+
if (Issues.standardFieldIds.includes(id) ||
|
|
451
|
+
Issues.fieldsToIgnore.includes(name)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
else if (name && value) {
|
|
455
|
+
try {
|
|
456
|
+
additionalFieldsMap = Object.assign(additionalFieldsMap, this.retrieveAdditionalFieldValue(ctx, name, value));
|
|
457
|
+
}
|
|
458
|
+
catch (err) {
|
|
459
|
+
this.logger.warn(`Failed to extract custom field ${name} on issue ${issue.id}. Skipping.`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
const additionalFields = [];
|
|
464
|
+
for (const [name, value] of Object.entries(additionalFieldsMap)) {
|
|
465
|
+
additionalFields.push({ name, value });
|
|
466
|
+
}
|
|
467
|
+
let description = null;
|
|
468
|
+
if (typeof issue.fields.description === 'string') {
|
|
469
|
+
description = issue.fields.description;
|
|
470
|
+
}
|
|
471
|
+
else if ((_j = issue.renderedFields) === null || _j === void 0 ? void 0 : _j.description) {
|
|
472
|
+
description = this.turndown.turndown(issue.renderedFields.description);
|
|
473
|
+
}
|
|
474
|
+
const creator = ((_k = issue.fields.creator) === null || _k === void 0 ? void 0 : _k.accountId) || ((_l = issue.fields.creator) === null || _l === void 0 ? void 0 : _l.name);
|
|
475
|
+
const parent = ((_m = issue.fields.parent) === null || _m === void 0 ? void 0 : _m.key)
|
|
476
|
+
? {
|
|
477
|
+
key: (_o = issue.fields.parent) === null || _o === void 0 ? void 0 : _o.key,
|
|
478
|
+
type: (_r = (_q = (_p = issue.fields.parent) === null || _p === void 0 ? void 0 : _p.fields) === null || _q === void 0 ? void 0 : _q.issuetype) === null || _r === void 0 ? void 0 : _r.name,
|
|
479
|
+
}
|
|
480
|
+
: null;
|
|
481
|
+
const epicKey = (parent === null || parent === void 0 ? void 0 : parent.type) === 'Epic' ? parent.key : this.getIssueEpic(issue);
|
|
482
|
+
const sprint = this.getSprintId(issue);
|
|
483
|
+
const type = (_s = issue.fields.issuetype) === null || _s === void 0 ? void 0 : _s.name;
|
|
484
|
+
const task = {
|
|
485
|
+
uid: issue.key,
|
|
486
|
+
name: issue.fields.summary,
|
|
487
|
+
description: this.truncate(ctx, description),
|
|
488
|
+
type: {
|
|
489
|
+
category: (_t = typeCategories.get(common_1.JiraCommon.normalize(type))) !== null && _t !== void 0 ? _t : 'Custom',
|
|
490
|
+
detail: type,
|
|
491
|
+
},
|
|
492
|
+
status: {
|
|
493
|
+
category: statusCategories.get(common_1.JiraCommon.normalize((_v = (_u = issue.fields.status) === null || _u === void 0 ? void 0 : _u.statusCategory) === null || _v === void 0 ? void 0 : _v.name)),
|
|
494
|
+
detail: (_w = issue.fields.status) === null || _w === void 0 ? void 0 : _w.name,
|
|
495
|
+
},
|
|
496
|
+
priority: (_x = issue.fields.priority) === null || _x === void 0 ? void 0 : _x.name,
|
|
497
|
+
createdAt: created,
|
|
498
|
+
updatedAt: faros_feeds_sdk_1.Utils.toDate(issue.fields.updated),
|
|
499
|
+
statusChangedAt: statusChanged,
|
|
500
|
+
statusChangelog,
|
|
501
|
+
points: (_y = this.getPoints(issue)) !== null && _y !== void 0 ? _y : null,
|
|
502
|
+
creator: creator ? { uid: creator, source } : null,
|
|
503
|
+
parent: (parent === null || parent === void 0 ? void 0 : parent.key) ? { uid: parent.key, source } : null,
|
|
504
|
+
epic: epicKey ? { uid: epicKey, source } : null,
|
|
505
|
+
sprint: sprint ? { uid: sprint, source } : null,
|
|
506
|
+
source,
|
|
507
|
+
additionalFields,
|
|
508
|
+
};
|
|
509
|
+
const excludeFields = this.excludeFields(ctx);
|
|
510
|
+
if (excludeFields.size > 0) {
|
|
511
|
+
const keys = Object.keys(task).filter((f) => !excludeFields.has(f));
|
|
512
|
+
results.push({ model: 'tms_Task', record: (0, lodash_1.pick)(task, keys) });
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
results.push({ model: 'tms_Task', record: task });
|
|
516
|
+
}
|
|
517
|
+
return results;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
exports.Issues = Issues;
|
|
521
|
+
Issues.issueFieldsStream = new converter_1.StreamName('jira', 'issue_fields');
|
|
522
|
+
Issues.pullRequestsStream = new converter_1.StreamName('jira', 'pull_requests');
|
|
523
|
+
Issues.workflowStatusesStream = new converter_1.StreamName('jira', 'workflow_statuses');
|
|
524
|
+
Issues.standardFieldIds = [
|
|
525
|
+
'assignee',
|
|
526
|
+
'created',
|
|
527
|
+
'creator',
|
|
528
|
+
'description',
|
|
529
|
+
'issuelinks',
|
|
530
|
+
'issuetype',
|
|
531
|
+
'labels',
|
|
532
|
+
'parent',
|
|
533
|
+
'priority',
|
|
534
|
+
'project',
|
|
535
|
+
'status',
|
|
536
|
+
'subtasks',
|
|
537
|
+
'summary',
|
|
538
|
+
'updated',
|
|
539
|
+
];
|
|
540
|
+
Issues.fieldsToIgnore = [
|
|
541
|
+
...common_1.JiraCommon.POINTS_FIELD_NAMES,
|
|
542
|
+
common_1.JiraCommon.DEV_FIELD_NAME,
|
|
543
|
+
common_1.JiraCommon.EPIC_LINK_FIELD_NAME,
|
|
544
|
+
common_1.JiraCommon.SPRINT_FIELD_NAME,
|
|
545
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AirbyteRecord } from 'faros-airbyte-cdk';
|
|
2
|
+
import { DestinationModel, DestinationRecord, StreamContext, StreamName } from '../converter';
|
|
3
|
+
import { JiraConverter } from './common';
|
|
4
|
+
export declare class ProjectVersions extends JiraConverter {
|
|
5
|
+
readonly destinationModels: ReadonlyArray<DestinationModel>;
|
|
6
|
+
private static readonly projectsStream;
|
|
7
|
+
get dependencies(): ReadonlyArray<StreamName>;
|
|
8
|
+
convert(record: AirbyteRecord, ctx: StreamContext): Promise<ReadonlyArray<DestinationRecord>>;
|
|
9
|
+
}
|