@acorex/connectivity 20.8.24 → 20.9.1

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.
Files changed (119) hide show
  1. package/fesm2022/{acorex-connectivity-api-execute.command-D2Q0ahw4.mjs → acorex-connectivity-api-execute.command-CjCFEav4.mjs} +16 -6
  2. package/fesm2022/acorex-connectivity-api-execute.command-CjCFEav4.mjs.map +1 -0
  3. package/fesm2022/acorex-connectivity-api.mjs +202 -47
  4. package/fesm2022/acorex-connectivity-api.mjs.map +1 -1
  5. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-g0RVU1Og.mjs +90679 -0
  6. package/fesm2022/acorex-connectivity-mock-acorex-connectivity-mock-g0RVU1Og.mjs.map +1 -0
  7. package/fesm2022/acorex-connectivity-mock-assign-to-manager.activity-CTrrsAvF.mjs +288 -0
  8. package/fesm2022/acorex-connectivity-mock-assign-to-manager.activity-CTrrsAvF.mjs.map +1 -0
  9. package/fesm2022/acorex-connectivity-mock-category-metadata-inheritance.query-CIof4zTg.mjs +200 -0
  10. package/fesm2022/acorex-connectivity-mock-category-metadata-inheritance.query-CIof4zTg.mjs.map +1 -0
  11. package/fesm2022/{acorex-connectivity-mock-category-with-items.query-DWW7t6nc.mjs → acorex-connectivity-mock-category-with-items.query-DAKUJIIt.mjs} +18 -17
  12. package/fesm2022/acorex-connectivity-mock-category-with-items.query-DAKUJIIt.mjs.map +1 -0
  13. package/fesm2022/acorex-connectivity-mock-chat-generate-image.command-CSbgiZEm.mjs +110 -0
  14. package/fesm2022/acorex-connectivity-mock-chat-generate-image.command-CSbgiZEm.mjs.map +1 -0
  15. package/fesm2022/acorex-connectivity-mock-chat-synthesize-speech.command-CjdySQzM.mjs +120 -0
  16. package/fesm2022/acorex-connectivity-mock-chat-synthesize-speech.command-CjdySQzM.mjs.map +1 -0
  17. package/fesm2022/acorex-connectivity-mock-chat-transcribe-speech.command-Wm1Ao81s.mjs +120 -0
  18. package/fesm2022/acorex-connectivity-mock-chat-transcribe-speech.command-Wm1Ao81s.mjs.map +1 -0
  19. package/fesm2022/{acorex-connectivity-mock-check-permission.command-DFcxfjxp.mjs → acorex-connectivity-mock-check-permission.activity-vr3OHtjC.mjs} +8 -16
  20. package/fesm2022/acorex-connectivity-mock-check-permission.activity-vr3OHtjC.mjs.map +1 -0
  21. package/fesm2022/acorex-connectivity-mock-content-management.module-GQdqKsPB.mjs +16 -0
  22. package/fesm2022/acorex-connectivity-mock-content-management.module-GQdqKsPB.mjs.map +1 -0
  23. package/fesm2022/{acorex-connectivity-mock-distribution-record.command-BopU0LyU.mjs → acorex-connectivity-mock-distribution-record.activity-a1_k9Czb.mjs} +29 -14
  24. package/fesm2022/acorex-connectivity-mock-distribution-record.activity-a1_k9Czb.mjs.map +1 -0
  25. package/fesm2022/acorex-connectivity-mock-entity-create.activity-CdoUzUvF.mjs +67 -0
  26. package/fesm2022/acorex-connectivity-mock-entity-create.activity-CdoUzUvF.mjs.map +1 -0
  27. package/fesm2022/acorex-connectivity-mock-entity-delete.activity-ErEN1c24.mjs +60 -0
  28. package/fesm2022/acorex-connectivity-mock-entity-delete.activity-ErEN1c24.mjs.map +1 -0
  29. package/fesm2022/acorex-connectivity-mock-entity-read.activity-1fJW8gVe.mjs +67 -0
  30. package/fesm2022/acorex-connectivity-mock-entity-read.activity-1fJW8gVe.mjs.map +1 -0
  31. package/fesm2022/acorex-connectivity-mock-entity-update.activity-06HTKiQQ.mjs +68 -0
  32. package/fesm2022/acorex-connectivity-mock-entity-update.activity-06HTKiQQ.mjs.map +1 -0
  33. package/fesm2022/acorex-connectivity-mock-extract-document-text.command-nGfUTSf6.mjs +64 -0
  34. package/fesm2022/acorex-connectivity-mock-extract-document-text.command-nGfUTSf6.mjs.map +1 -0
  35. package/fesm2022/{acorex-connectivity-mock-get-application-versions-chart-data.query-uwDUrbFJ.mjs → acorex-connectivity-mock-get-application-versions-chart-data.query-DwVuYuKx.mjs} +4 -4
  36. package/fesm2022/acorex-connectivity-mock-get-application-versions-chart-data.query-DwVuYuKx.mjs.map +1 -0
  37. package/fesm2022/{acorex-connectivity-mock-get-application-versions-timeline.query-BHjQYTyZ.mjs → acorex-connectivity-mock-get-application-versions-timeline.query-sFKYynZA.mjs} +4 -4
  38. package/fesm2022/acorex-connectivity-mock-get-application-versions-timeline.query-sFKYynZA.mjs.map +1 -0
  39. package/fesm2022/acorex-connectivity-mock-get-current-session-user.activity-CsmxwXsM.mjs +39 -0
  40. package/fesm2022/acorex-connectivity-mock-get-current-session-user.activity-CsmxwXsM.mjs.map +1 -0
  41. package/fesm2022/acorex-connectivity-mock-get-current-user-manager.activity-C1mj2bgB.mjs +69 -0
  42. package/fesm2022/acorex-connectivity-mock-get-current-user-manager.activity-C1mj2bgB.mjs.map +1 -0
  43. package/fesm2022/{acorex-connectivity-mock-get-employee-list.query-Ch-Vh5GE.mjs → acorex-connectivity-mock-get-employee-list.query-BWbZj3tp.mjs} +8 -7
  44. package/fesm2022/acorex-connectivity-mock-get-employee-list.query-BWbZj3tp.mjs.map +1 -0
  45. package/fesm2022/{acorex-connectivity-mock-get-location-list.query-Xbc6d8kb.mjs → acorex-connectivity-mock-get-location-list.query-CQ2rFDUM.mjs} +5 -5
  46. package/fesm2022/acorex-connectivity-mock-get-location-list.query-CQ2rFDUM.mjs.map +1 -0
  47. package/fesm2022/{acorex-connectivity-mock-get-product-chart-data.query-m8_ME45B.mjs → acorex-connectivity-mock-get-product-chart-data.query-D7DBzLT-.mjs} +4 -4
  48. package/fesm2022/acorex-connectivity-mock-get-product-chart-data.query-D7DBzLT-.mjs.map +1 -0
  49. package/fesm2022/{acorex-connectivity-mock-get-product-list.query-DzkssYRw.mjs → acorex-connectivity-mock-get-product-list.query-o9TcY_RC.mjs} +20 -12
  50. package/fesm2022/acorex-connectivity-mock-get-product-list.query-o9TcY_RC.mjs.map +1 -0
  51. package/fesm2022/{acorex-connectivity-mock-get-product-pdf-data.query-wMD65pwR.mjs → acorex-connectivity-mock-get-product-pdf-data.query-DUZvwsmY.mjs} +5 -5
  52. package/fesm2022/acorex-connectivity-mock-get-product-pdf-data.query-DUZvwsmY.mjs.map +1 -0
  53. package/fesm2022/{acorex-connectivity-mock-get-subscriptions-chart-data.query-DBOT_0IN.mjs → acorex-connectivity-mock-get-subscriptions-chart-data.query-BXDzY2Sd.mjs} +5 -5
  54. package/fesm2022/acorex-connectivity-mock-get-subscriptions-chart-data.query-BXDzY2Sd.mjs.map +1 -0
  55. package/fesm2022/{acorex-connectivity-mock-get-subscriptions-timeline.query-DBEEbeiS.mjs → acorex-connectivity-mock-get-subscriptions-timeline.query-D_jVT-7a.mjs} +6 -6
  56. package/fesm2022/acorex-connectivity-mock-get-subscriptions-timeline.query-D_jVT-7a.mjs.map +1 -0
  57. package/fesm2022/{acorex-connectivity-mock-get-tenant-application-access.query-BM9toJ45.mjs → acorex-connectivity-mock-get-tenant-application-access.query-BG6t0137.mjs} +6 -6
  58. package/fesm2022/acorex-connectivity-mock-get-tenant-application-access.query-BG6t0137.mjs.map +1 -0
  59. package/fesm2022/{acorex-connectivity-mock-get-tenant-registration-chart-data.query-CACCBXn-.mjs → acorex-connectivity-mock-get-tenant-registration-chart-data.query-CgMZxfzh.mjs} +5 -5
  60. package/fesm2022/acorex-connectivity-mock-get-tenant-registration-chart-data.query-CgMZxfzh.mjs.map +1 -0
  61. package/fesm2022/{acorex-connectivity-mock-get-tenant-registration-timeline.query-CfDjhtaC.mjs → acorex-connectivity-mock-get-tenant-registration-timeline.query-COmTsDCV.mjs} +5 -5
  62. package/fesm2022/acorex-connectivity-mock-get-tenant-registration-timeline.query-COmTsDCV.mjs.map +1 -0
  63. package/fesm2022/{acorex-connectivity-mock-get-tenant-user-distribution.query-CZXvavUh.mjs → acorex-connectivity-mock-get-tenant-user-distribution.query-gqSqvIaa.mjs} +6 -6
  64. package/fesm2022/acorex-connectivity-mock-get-tenant-user-distribution.query-gqSqvIaa.mjs.map +1 -0
  65. package/fesm2022/acorex-connectivity-mock-if.activity-DvzuhItL.mjs +35 -0
  66. package/fesm2022/acorex-connectivity-mock-if.activity-DvzuhItL.mjs.map +1 -0
  67. package/fesm2022/acorex-connectivity-mock-index-D0jdkk2E.mjs +99 -0
  68. package/fesm2022/acorex-connectivity-mock-index-D0jdkk2E.mjs.map +1 -0
  69. package/fesm2022/acorex-connectivity-mock-jira-instance-sync.command-CaOd4PJa.mjs +474 -0
  70. package/fesm2022/acorex-connectivity-mock-jira-instance-sync.command-CaOd4PJa.mjs.map +1 -0
  71. package/fesm2022/acorex-connectivity-mock-notification-management-email-send.command-BuH_Lm6V.mjs +72 -0
  72. package/fesm2022/acorex-connectivity-mock-notification-management-email-send.command-BuH_Lm6V.mjs.map +1 -0
  73. package/fesm2022/acorex-connectivity-mock-report-summary.util-CGOhHIZr.mjs +56 -0
  74. package/fesm2022/acorex-connectivity-mock-report-summary.util-CGOhHIZr.mjs.map +1 -0
  75. package/fesm2022/{acorex-connectivity-mock-sample.command-CXz1poTn.mjs → acorex-connectivity-mock-sample.command-CJmDL4pL.mjs} +4 -4
  76. package/fesm2022/acorex-connectivity-mock-sample.command-CJmDL4pL.mjs.map +1 -0
  77. package/fesm2022/acorex-connectivity-mock-structured-text-completion.command-l31pjl9-.mjs +38 -0
  78. package/fesm2022/acorex-connectivity-mock-structured-text-completion.command-l31pjl9-.mjs.map +1 -0
  79. package/fesm2022/acorex-connectivity-mock-user-roles-for-list-column.query-wRFHOp-X.mjs +30 -0
  80. package/fesm2022/acorex-connectivity-mock-user-roles-for-list-column.query-wRFHOp-X.mjs.map +1 -0
  81. package/fesm2022/acorex-connectivity-mock.mjs +2 -51673
  82. package/fesm2022/acorex-connectivity-mock.mjs.map +1 -1
  83. package/fesm2022/acorex-connectivity-utils.mjs +7 -7
  84. package/fesm2022/acorex-connectivity-utils.mjs.map +1 -1
  85. package/fesm2022/acorex-connectivity.mjs.map +1 -1
  86. package/package.json +8 -7
  87. package/{api/index.d.ts → types/acorex-connectivity-api.d.ts} +21 -2
  88. package/types/acorex-connectivity-mock.d.ts +4136 -0
  89. package/fesm2022/acorex-connectivity-api-execute.command-D2Q0ahw4.mjs.map +0 -1
  90. package/fesm2022/acorex-connectivity-mock-assign-to-manager.command-CzzTHBVX.mjs +0 -66
  91. package/fesm2022/acorex-connectivity-mock-assign-to-manager.command-CzzTHBVX.mjs.map +0 -1
  92. package/fesm2022/acorex-connectivity-mock-category-with-items.query-DWW7t6nc.mjs.map +0 -1
  93. package/fesm2022/acorex-connectivity-mock-check-permission.command-DFcxfjxp.mjs.map +0 -1
  94. package/fesm2022/acorex-connectivity-mock-complete-signature-process.command-BG_rxbUl.mjs +0 -80
  95. package/fesm2022/acorex-connectivity-mock-complete-signature-process.command-BG_rxbUl.mjs.map +0 -1
  96. package/fesm2022/acorex-connectivity-mock-distribution-record.command-BopU0LyU.mjs.map +0 -1
  97. package/fesm2022/acorex-connectivity-mock-get-application-versions-chart-data.query-uwDUrbFJ.mjs.map +0 -1
  98. package/fesm2022/acorex-connectivity-mock-get-application-versions-timeline.query-BHjQYTyZ.mjs.map +0 -1
  99. package/fesm2022/acorex-connectivity-mock-get-employee-list.query-Ch-Vh5GE.mjs.map +0 -1
  100. package/fesm2022/acorex-connectivity-mock-get-location-list.query-Xbc6d8kb.mjs.map +0 -1
  101. package/fesm2022/acorex-connectivity-mock-get-product-chart-data.query-m8_ME45B.mjs.map +0 -1
  102. package/fesm2022/acorex-connectivity-mock-get-product-list.query-DzkssYRw.mjs.map +0 -1
  103. package/fesm2022/acorex-connectivity-mock-get-product-pdf-data.query-wMD65pwR.mjs.map +0 -1
  104. package/fesm2022/acorex-connectivity-mock-get-subscriptions-chart-data.query-DBOT_0IN.mjs.map +0 -1
  105. package/fesm2022/acorex-connectivity-mock-get-subscriptions-timeline.query-DBEEbeiS.mjs.map +0 -1
  106. package/fesm2022/acorex-connectivity-mock-get-tenant-application-access.query-BM9toJ45.mjs.map +0 -1
  107. package/fesm2022/acorex-connectivity-mock-get-tenant-registration-chart-data.query-CACCBXn-.mjs.map +0 -1
  108. package/fesm2022/acorex-connectivity-mock-get-tenant-registration-timeline.query-CfDjhtaC.mjs.map +0 -1
  109. package/fesm2022/acorex-connectivity-mock-get-tenant-user-distribution.query-CZXvavUh.mjs.map +0 -1
  110. package/fesm2022/acorex-connectivity-mock-notify-signers.command-BV-b8NBg.mjs +0 -69
  111. package/fesm2022/acorex-connectivity-mock-notify-signers.command-BV-b8NBg.mjs.map +0 -1
  112. package/fesm2022/acorex-connectivity-mock-request-signature.command-DZyVnhAp.mjs +0 -72
  113. package/fesm2022/acorex-connectivity-mock-request-signature.command-DZyVnhAp.mjs.map +0 -1
  114. package/fesm2022/acorex-connectivity-mock-sample.command-CXz1poTn.mjs.map +0 -1
  115. package/fesm2022/acorex-connectivity-mock-validate-all-signatures.command-leYngRtS.mjs +0 -81
  116. package/fesm2022/acorex-connectivity-mock-validate-all-signatures.command-leYngRtS.mjs.map +0 -1
  117. package/mock/index.d.ts +0 -3022
  118. /package/{utils/index.d.ts → types/acorex-connectivity-utils.d.ts} +0 -0
  119. /package/{index.d.ts → types/acorex-connectivity.d.ts} +0 -0
@@ -0,0 +1,474 @@
1
+ import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
2
+ import { AXTranslationService } from '@acorex/core/translation';
3
+ import { RootConfig } from '@acorex/modules/jira-management';
4
+ import * as i0 from '@angular/core';
5
+ import { inject, Injectable } from '@angular/core';
6
+ import { trim, defaultTo, isEmpty, get, isString } from 'lodash-es';
7
+ import { createMultiLanguageString } from '@acorex/platform/contracts';
8
+ import { AXPEntityStorageService } from '@acorex/platform/layout/entity';
9
+ import { AXPIntegrationRuntimeService } from '@acorex/platform/common';
10
+
11
+ //#region ---- Imports ----
12
+ class JiraApiError extends Error {
13
+ constructor(message, status, body) {
14
+ super(message);
15
+ this.status = status;
16
+ this.body = body;
17
+ this.name = 'JiraApiError';
18
+ }
19
+ }
20
+ //#endregion
21
+ //#region ---- Constants ----
22
+ const JIRA_DEV_PROXY_PREFIX = '/connectivity/mock/jira-proxy';
23
+ //#endregion
24
+ //#region ---- Helpers ----
25
+ function shouldUseDevJiraProxy() {
26
+ if (typeof window === 'undefined') {
27
+ return false;
28
+ }
29
+ return /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i.test(window.location.origin);
30
+ }
31
+ function buildApiRoot(baseUrl, apiVersion) {
32
+ const base = trim(baseUrl).replace(/\/+$/, '');
33
+ const directRoot = `${base}/rest/api/${apiVersion}`;
34
+ if (!shouldUseDevJiraProxy()) {
35
+ return directRoot;
36
+ }
37
+ try {
38
+ const { host } = new URL(base);
39
+ return `${JIRA_DEV_PROXY_PREFIX}/${host}/rest/api/${apiVersion}`;
40
+ }
41
+ catch {
42
+ return directRoot;
43
+ }
44
+ }
45
+ //#endregion
46
+ //#region ---- Client ----
47
+ class JiraApiClient {
48
+ constructor(options) {
49
+ const version = defaultTo(trim(defaultTo(options.apiVersion, '')), '2');
50
+ this.apiRoot = buildApiRoot(options.baseUrl, version);
51
+ this.token = trim(options.token);
52
+ }
53
+ async get(path, query) {
54
+ const url = new URL(`${this.apiRoot}${path.startsWith('/') ? path : `/${path}`}`, typeof window !== 'undefined' ? window.location.origin : 'http://localhost');
55
+ if (query) {
56
+ for (const [key, value] of Object.entries(query)) {
57
+ if (value !== undefined && value !== null && value !== '') {
58
+ url.searchParams.set(key, String(value));
59
+ }
60
+ }
61
+ }
62
+ const response = await fetch(url.toString(), {
63
+ method: 'GET',
64
+ headers: {
65
+ Accept: 'application/json',
66
+ Authorization: `Bearer ${this.token}`,
67
+ },
68
+ });
69
+ const bodyText = await response.text();
70
+ if (!response.ok) {
71
+ throw new JiraApiError(`Jira API request failed (${response.status} ${response.statusText})`, response.status, bodyText);
72
+ }
73
+ if (isEmpty(bodyText)) {
74
+ return {};
75
+ }
76
+ try {
77
+ return JSON.parse(bodyText);
78
+ }
79
+ catch {
80
+ throw new JiraApiError('Jira API returned invalid JSON', response.status, bodyText);
81
+ }
82
+ }
83
+ }
84
+ function readIssueField(issue, path) {
85
+ return get(issue.fields, path);
86
+ }
87
+ //#endregion
88
+
89
+ //#region ---- Imports ----
90
+ //#endregion
91
+ //#region ---- Service ----
92
+ class AXCJiraInstanceSyncService {
93
+ constructor() {
94
+ //#region ---- Services & Dependencies ----
95
+ this.storage = inject(AXPEntityStorageService);
96
+ this.integrationRuntime = inject(AXPIntegrationRuntimeService, { optional: true });
97
+ this.instanceEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraInstance.name}`;
98
+ this.projectEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProject.name}`;
99
+ this.issueTypeEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraIssueType.name}`;
100
+ this.fieldEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraField.name}`;
101
+ this.projectIssueTypeEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProjectIssueType.name}`;
102
+ this.projectIssueTypeFieldEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProjectIssueTypeField.name}`;
103
+ this.workflowStatusEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraWorkflowStatus.name}`;
104
+ this.issueEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraIssue.name}`;
105
+ this.worklogEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraWorklog.name}`;
106
+ }
107
+ //#endregion
108
+ //#region ---- Public API ----
109
+ async sync(input) {
110
+ const instance = (await this.storage.getOne(this.instanceEntity, input.instanceId));
111
+ if (!instance) {
112
+ throw new Error('Jira instance not found.');
113
+ }
114
+ const token = await this.resolveToken(instance);
115
+ const baseUrl = defaultTo(trim(defaultTo(instance.baseUrl, '')), trim(defaultTo(instance.siteUrl, '')));
116
+ if (!baseUrl) {
117
+ throw new Error('Configure base URL before syncing.');
118
+ }
119
+ const client = new JiraApiClient({
120
+ baseUrl,
121
+ token,
122
+ apiVersion: instance.apiVersion,
123
+ });
124
+ const [jiraProjects, jiraIssueTypes, jiraFields, existingProjects, existingIssueTypes, existingFields, existingProjectIssueTypes, existingProjectIssueTypeFields, existingWorkflowStatuses, existingIssues, existingWorklogs,] = await Promise.all([
125
+ client.get('/project'),
126
+ client.get('/issuetype'),
127
+ client.get('/field'),
128
+ this.loadAll(this.projectEntity),
129
+ this.loadAll(this.issueTypeEntity),
130
+ this.loadAll(this.fieldEntity),
131
+ this.loadAll(this.projectIssueTypeEntity),
132
+ this.loadAll(this.projectIssueTypeFieldEntity),
133
+ this.loadAll(this.workflowStatusEntity),
134
+ this.loadAll(this.issueEntity),
135
+ this.loadAll(this.worklogEntity),
136
+ ]);
137
+ const instanceTitle = instance.title;
138
+ const instanceName = instance.name;
139
+ let projectIssueTypes = 0;
140
+ let projectIssueTypeFields = 0;
141
+ let workflowStatuses = 0;
142
+ let issues = 0;
143
+ let worklogs = 0;
144
+ const issueTypeIdByJiraId = new Map();
145
+ for (const jiraIssueType of jiraIssueTypes) {
146
+ const id = await this.upsertRow(this.issueTypeEntity, existingIssueTypes, (row) => row['jiraInstanceId'] === instance.id && row['jiraIssueTypeId'] === jiraIssueType.id, {
147
+ jiraInstanceId: instance.id,
148
+ jiraInstance: { id: instance.id, title: instanceTitle },
149
+ jiraIssueTypeId: jiraIssueType.id,
150
+ name: jiraIssueType.name,
151
+ description: jiraIssueType.description ? createMultiLanguageString(jiraIssueType.description) : null,
152
+ subtask: jiraIssueType.subtask === true,
153
+ hierarchyLevel: defaultTo(jiraIssueType.hierarchyLevel, 0),
154
+ iconUrl: jiraIssueType.iconUrl ?? null,
155
+ });
156
+ issueTypeIdByJiraId.set(jiraIssueType.id, id);
157
+ }
158
+ const fieldIdByJiraFieldId = new Map();
159
+ for (const jiraField of jiraFields) {
160
+ const fieldId = await this.upsertRow(this.fieldEntity, existingFields, (row) => row['jiraInstanceId'] === instance.id && row['jiraFieldId'] === jiraField.id, {
161
+ jiraInstanceId: instance.id,
162
+ jiraInstance: { id: instance.id, name: instanceName },
163
+ jiraFieldId: jiraField.id,
164
+ name: jiraField.name,
165
+ custom: jiraField.custom === true,
166
+ fieldType: get(jiraField, 'schema.type') ?? null,
167
+ schema: get(jiraField, 'schema.custom') ?? null,
168
+ });
169
+ fieldIdByJiraFieldId.set(jiraField.id, fieldId);
170
+ }
171
+ const projectIdByJiraId = new Map();
172
+ for (const jiraProject of jiraProjects) {
173
+ const projectId = await this.upsertRow(this.projectEntity, existingProjects, (row) => row['jiraInstanceId'] === instance.id && row['jiraProjectId'] === jiraProject.id, {
174
+ jiraInstanceId: instance.id,
175
+ jiraInstance: { id: instance.id, title: instanceTitle, name: instanceName },
176
+ jiraProjectId: jiraProject.id,
177
+ key: jiraProject.key,
178
+ name: jiraProject.name,
179
+ projectTypeKey: jiraProject.projectTypeKey ?? null,
180
+ style: jiraProject.style ?? null,
181
+ simplified: jiraProject.simplified ?? null,
182
+ leadAccountId: jiraProject.lead?.accountId ?? null,
183
+ leadDisplayName: jiraProject.lead?.displayName ?? null,
184
+ avatarUrl: jiraProject.avatarUrls?.['48x48'] ?? null,
185
+ description: jiraProject.description ? createMultiLanguageString(jiraProject.description) : null,
186
+ projectStatusId: 'Active',
187
+ });
188
+ projectIdByJiraId.set(jiraProject.id, projectId);
189
+ const statusesByIssueType = await client.get(`/project/${jiraProject.key}/statuses`);
190
+ const linkedIssueTypeIds = new Set();
191
+ for (const issueTypeBlock of statusesByIssueType) {
192
+ const localIssueTypeId = issueTypeIdByJiraId.get(issueTypeBlock.id);
193
+ if (!localIssueTypeId) {
194
+ continue;
195
+ }
196
+ linkedIssueTypeIds.add(localIssueTypeId);
197
+ await this.upsertRow(this.projectIssueTypeEntity, existingProjectIssueTypes, (row) => row['projectId'] === projectId && row['issueTypeId'] === localIssueTypeId, {
198
+ projectId,
199
+ project: { id: projectId, key: jiraProject.key, name: jiraProject.name },
200
+ issueTypeId: localIssueTypeId,
201
+ issueType: { id: localIssueTypeId, name: issueTypeBlock.name },
202
+ });
203
+ projectIssueTypes += 1;
204
+ let order = 0;
205
+ for (const status of issueTypeBlock.statuses) {
206
+ order += 1;
207
+ await this.upsertRow(this.workflowStatusEntity, existingWorkflowStatuses, (row) => row['projectId'] === projectId &&
208
+ row['issueTypeId'] === localIssueTypeId &&
209
+ row['jiraStatusId'] === status.id, {
210
+ projectId,
211
+ project: { id: projectId, key: jiraProject.key, name: jiraProject.name },
212
+ issueTypeId: localIssueTypeId,
213
+ issueType: { id: localIssueTypeId, name: issueTypeBlock.name },
214
+ jiraStatusId: status.id,
215
+ name: status.name,
216
+ statusCategoryKey: this.mapStatusCategory(status.statusCategory?.key),
217
+ order,
218
+ });
219
+ workflowStatuses += 1;
220
+ }
221
+ }
222
+ const createMeta = await client.get('/issue/createmeta', {
223
+ projectKeys: jiraProject.key,
224
+ expand: 'projects.issuetypes.fields',
225
+ });
226
+ for (const projectMeta of createMeta.projects ?? []) {
227
+ for (const issueTypeMeta of projectMeta.issuetypes ?? []) {
228
+ const localIssueTypeId = issueTypeIdByJiraId.get(issueTypeMeta.id);
229
+ if (!localIssueTypeId || !linkedIssueTypeIds.has(localIssueTypeId)) {
230
+ continue;
231
+ }
232
+ let fieldOrder = 0;
233
+ for (const [jiraFieldKey, fieldMeta] of Object.entries(issueTypeMeta.fields ?? {})) {
234
+ const localFieldId = fieldIdByJiraFieldId.get(jiraFieldKey);
235
+ if (!localFieldId) {
236
+ continue;
237
+ }
238
+ fieldOrder += 1;
239
+ await this.upsertRow(this.projectIssueTypeFieldEntity, existingProjectIssueTypeFields, (row) => row['projectId'] === projectId &&
240
+ row['issueTypeId'] === localIssueTypeId &&
241
+ row['fieldId'] === localFieldId, {
242
+ projectId,
243
+ project: { id: projectId, key: jiraProject.key, name: jiraProject.name },
244
+ issueTypeId: localIssueTypeId,
245
+ issueType: { id: localIssueTypeId, name: issueTypeBlockName(issueTypeMeta.id, statusesByIssueType) },
246
+ fieldId: localFieldId,
247
+ field: { id: localFieldId, jiraFieldId: jiraFieldKey, name: jiraFieldKey },
248
+ required: fieldMeta.required === true,
249
+ hasDefaultValue: fieldMeta.hasDefaultValue === true,
250
+ defaultValue: fieldMeta.defaultValue != null ? JSON.stringify(fieldMeta.defaultValue) : null,
251
+ allowedValues: fieldMeta.allowedValues && fieldMeta.allowedValues.length > 0
252
+ ? JSON.stringify(fieldMeta.allowedValues)
253
+ : null,
254
+ order: fieldOrder,
255
+ });
256
+ projectIssueTypeFields += 1;
257
+ }
258
+ }
259
+ }
260
+ const search = await client.get('/search', {
261
+ jql: `project = ${jiraProject.key} ORDER BY updated DESC`,
262
+ maxResults: 50,
263
+ fields: 'summary,description,issuetype,status,assignee,reporter,priority,parent,resolution,labels,created,updated',
264
+ });
265
+ for (const jiraIssue of search.issues ?? []) {
266
+ const jiraIssueTypeId = readIssueField(jiraIssue, 'issuetype.id')?.id;
267
+ const jiraStatusId = readIssueField(jiraIssue, 'status.id')?.id;
268
+ const localIssueTypeId = jiraIssueTypeId ? issueTypeIdByJiraId.get(jiraIssueTypeId) : undefined;
269
+ const workflowStatus = existingWorkflowStatuses.find((row) => row['projectId'] === projectId &&
270
+ row['issueTypeId'] === localIssueTypeId &&
271
+ row['jiraStatusId'] === jiraStatusId);
272
+ const parentJiraId = readIssueField(jiraIssue, 'parent.id')?.id;
273
+ const parentIssue = parentJiraId
274
+ ? existingIssues.find((row) => row['jiraIssueId'] === parentJiraId)
275
+ : undefined;
276
+ const issueId = await this.upsertRow(this.issueEntity, existingIssues, (row) => row['jiraInstanceId'] === instance.id && row['jiraIssueId'] === jiraIssue.id, {
277
+ jiraInstanceId: instance.id,
278
+ jiraInstance: { id: instance.id, name: instanceName },
279
+ projectId,
280
+ project: { id: projectId, key: jiraProject.key, name: jiraProject.name },
281
+ issueTypeId: localIssueTypeId ?? '',
282
+ issueType: localIssueTypeId
283
+ ? { id: localIssueTypeId, name: readIssueField(jiraIssue, 'issuetype.name')?.name }
284
+ : undefined,
285
+ workflowStatusId: workflowStatus?.id ?? '',
286
+ workflowStatus: workflowStatus
287
+ ? {
288
+ id: workflowStatus.id,
289
+ name: workflowStatus['name'],
290
+ statusCategoryKey: workflowStatus['statusCategoryKey'],
291
+ }
292
+ : undefined,
293
+ jiraIssueId: jiraIssue.id,
294
+ jiraIssueKey: jiraIssue.key,
295
+ summary: defaultTo(readIssueField(jiraIssue, 'summary'), jiraIssue.key),
296
+ description: readIssueField(jiraIssue, 'description') ?? null,
297
+ assigneeAccountId: readIssueField(jiraIssue, 'assignee.accountId')?.accountId ?? null,
298
+ assigneeDisplayName: readIssueField(jiraIssue, 'assignee.displayName')?.displayName ?? null,
299
+ reporterAccountId: readIssueField(jiraIssue, 'reporter.accountId')?.accountId ?? null,
300
+ reporterDisplayName: readIssueField(jiraIssue, 'reporter.displayName')?.displayName ?? null,
301
+ priorityName: readIssueField(jiraIssue, 'priority.name')?.name ?? null,
302
+ parentIssueId: parentIssue?.id ?? null,
303
+ parentIssue: parentIssue
304
+ ? { id: parentIssue.id, jiraIssueKey: parentIssue['jiraIssueKey'] }
305
+ : undefined,
306
+ resolutionName: readIssueField(jiraIssue, 'resolution.name')?.name ?? null,
307
+ labels: JSON.stringify(readIssueField(jiraIssue, 'labels') ?? []),
308
+ jiraCreated: readIssueField(jiraIssue, 'created') ?? null,
309
+ jiraUpdated: readIssueField(jiraIssue, 'updated') ?? null,
310
+ });
311
+ issues += 1;
312
+ const worklogList = await client.get(`/issue/${jiraIssue.key}/worklog`);
313
+ for (const worklog of worklogList.worklogs ?? []) {
314
+ await this.upsertRow(this.worklogEntity, existingWorklogs, (row) => row['issueId'] === issueId && row['jiraWorklogId'] === worklog.id, {
315
+ issueId,
316
+ issue: { id: issueId, jiraIssueKey: jiraIssue.key, summary: readIssueField(jiraIssue, 'summary') },
317
+ jiraWorklogId: worklog.id,
318
+ authorAccountId: worklog.author?.accountId ?? null,
319
+ authorDisplayName: worklog.author?.displayName ?? null,
320
+ started: worklog.started,
321
+ timeSpentSeconds: worklog.timeSpentSeconds,
322
+ timeSpentDisplay: worklog.timeSpent ?? null,
323
+ comment: isString(worklog.comment) ? worklog.comment : null,
324
+ jiraCreated: worklog.created ?? null,
325
+ jiraUpdated: worklog.updated ?? null,
326
+ });
327
+ worklogs += 1;
328
+ }
329
+ }
330
+ }
331
+ await this.storage.updateOne(this.instanceEntity, instance.id, {
332
+ lastSyncAt: new Date().toISOString(),
333
+ });
334
+ return {
335
+ instanceId: instance.id,
336
+ projects: jiraProjects.length,
337
+ issueTypes: jiraIssueTypes.length,
338
+ fields: jiraFields.length,
339
+ workflowStatuses,
340
+ projectIssueTypes,
341
+ projectIssueTypeFields,
342
+ issues,
343
+ worklogs,
344
+ };
345
+ }
346
+ //#endregion
347
+ //#region ---- Utility Methods ----
348
+ async resolveToken(instance) {
349
+ if (instance.integrationConnectionId && this.integrationRuntime) {
350
+ const client = await this.integrationRuntime.withClient({ providerId: 'jira', connectionScope: 'tenant', connectionKey: instance.name }, async (resolved) => resolved);
351
+ const token = trim(defaultTo(client.token, ''));
352
+ if (token) {
353
+ return token;
354
+ }
355
+ }
356
+ const adminToken = trim(defaultTo(instance.adminToken, ''));
357
+ if (adminToken) {
358
+ return adminToken;
359
+ }
360
+ const pat = trim(defaultTo(instance.personalAccessToken, ''));
361
+ if (pat) {
362
+ return pat;
363
+ }
364
+ throw new Error('Configure an integration connection or personal access token before syncing.');
365
+ }
366
+ async loadAll(entityName) {
367
+ const result = await this.storage.query(entityName, { skip: 0, take: 50_000 });
368
+ return (result.items ?? []);
369
+ }
370
+ async upsertRow(entityName, cache, match, payload) {
371
+ const existing = cache.find(match);
372
+ if (existing) {
373
+ await this.storage.updateOne(entityName, existing.id, payload);
374
+ Object.assign(existing, payload);
375
+ return existing.id;
376
+ }
377
+ const id = crypto.randomUUID();
378
+ await this.storage.insertOne(entityName, { id, ...payload });
379
+ const created = { id, ...payload };
380
+ cache.push(created);
381
+ return id;
382
+ }
383
+ mapStatusCategory(key) {
384
+ if (key === 'done') {
385
+ return 'done';
386
+ }
387
+ if (key === 'indeterminate') {
388
+ return 'indeterminate';
389
+ }
390
+ return 'new';
391
+ }
392
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
393
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncService, providedIn: 'root' }); }
394
+ }
395
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncService, decorators: [{
396
+ type: Injectable,
397
+ args: [{ providedIn: 'root' }]
398
+ }] });
399
+ function issueTypeBlockName(issueTypeId, blocks) {
400
+ return blocks.find((block) => block.id === issueTypeId)?.name ?? issueTypeId;
401
+ }
402
+
403
+ const I18N = `${RootConfig.config.i18n}:instances.entities.instance`;
404
+ //#endregion
405
+ //#region ---- Command ----
406
+ class AXCJiraInstanceSyncCommand {
407
+ constructor() {
408
+ //#region ---- Services & Dependencies ----
409
+ this.syncService = inject(AXCJiraInstanceSyncService);
410
+ this.loadingDialog = inject(AXLoadingDialogService);
411
+ this.translation = inject(AXTranslationService);
412
+ }
413
+ //#endregion
414
+ //#region ---- Command Execution ----
415
+ async execute(input) {
416
+ const instanceId = defaultTo(get(input, 'instanceId'), '').trim();
417
+ if (!instanceId) {
418
+ return {
419
+ success: false,
420
+ message: {
421
+ text: await this.translation.translateAsync(`@${I18N}.actions.sync.messages.missing-instance`),
422
+ },
423
+ };
424
+ }
425
+ const [loadingTitle, loadingDescription] = await Promise.all([
426
+ this.translation.translateAsync(`@${I18N}.actions.sync.loading.title`),
427
+ this.translation.translateAsync(`@${I18N}.actions.sync.loading.description`),
428
+ ]);
429
+ const progressDialog = this.loadingDialog.show({
430
+ title: loadingTitle,
431
+ mode: 'indeterminate',
432
+ progressColor: 'primary',
433
+ text: loadingDescription,
434
+ });
435
+ try {
436
+ const data = await this.syncService.sync({ instanceId });
437
+ return {
438
+ success: true,
439
+ data,
440
+ message: {
441
+ text: await this.translation.translateAsync(`@${I18N}.actions.sync.messages.success`, {
442
+ params: {
443
+ projects: data.projects,
444
+ issues: data.issues,
445
+ },
446
+ }),
447
+ },
448
+ };
449
+ }
450
+ catch (error) {
451
+ const fallback = await this.translation.translateAsync(`@${I18N}.actions.sync.messages.failed`);
452
+ let text = error instanceof Error ? error.message : fallback;
453
+ if (error instanceof JiraApiError && error.status === 0) {
454
+ text = await this.translation.translateAsync(`@${I18N}.actions.sync.messages.network-error`);
455
+ }
456
+ return {
457
+ success: false,
458
+ message: { text },
459
+ };
460
+ }
461
+ finally {
462
+ progressDialog.close();
463
+ }
464
+ }
465
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
466
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncCommand, providedIn: 'root' }); }
467
+ }
468
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXCJiraInstanceSyncCommand, decorators: [{
469
+ type: Injectable,
470
+ args: [{ providedIn: 'root' }]
471
+ }] });
472
+
473
+ export { AXCJiraInstanceSyncCommand };
474
+ //# sourceMappingURL=acorex-connectivity-mock-jira-instance-sync.command-CaOd4PJa.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-connectivity-mock-jira-instance-sync.command-CaOd4PJa.mjs","sources":["../../../../libs/connectivity/mock/src/lib/jira-management/features/jira-instance-sync/jira-api.client.ts","../../../../libs/connectivity/mock/src/lib/jira-management/features/jira-instance-sync/jira-instance-sync.service.ts","../../../../libs/connectivity/mock/src/lib/jira-management/features/jira-instance-sync/jira-instance-sync.command.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { defaultTo, get, isEmpty, trim } from 'lodash-es';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface JiraApiClientOptions {\n baseUrl: string;\n token: string;\n apiVersion?: string | null;\n}\n\nexport class JiraApiError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n readonly body?: string,\n ) {\n super(message);\n this.name = 'JiraApiError';\n }\n}\n\n//#endregion\n\n//#region ---- Constants ----\n\nconst JIRA_DEV_PROXY_PREFIX = '/connectivity/mock/jira-proxy';\n\n//#endregion\n\n//#region ---- Helpers ----\n\nfunction shouldUseDevJiraProxy(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n return /^https?:\\/\\/(localhost|127\\.0\\.0\\.1)(:\\d+)?$/i.test(window.location.origin);\n}\n\nfunction buildApiRoot(baseUrl: string, apiVersion: string): string {\n const base = trim(baseUrl).replace(/\\/+$/, '');\n const directRoot = `${base}/rest/api/${apiVersion}`;\n\n if (!shouldUseDevJiraProxy()) {\n return directRoot;\n }\n\n try {\n const { host } = new URL(base);\n return `${JIRA_DEV_PROXY_PREFIX}/${host}/rest/api/${apiVersion}`;\n } catch {\n return directRoot;\n }\n}\n\n//#endregion\n\n//#region ---- Client ----\n\nexport class JiraApiClient {\n private readonly apiRoot: string;\n private readonly token: string;\n\n constructor(options: JiraApiClientOptions) {\n const version = defaultTo(trim(defaultTo(options.apiVersion, '')), '2');\n this.apiRoot = buildApiRoot(options.baseUrl, version);\n this.token = trim(options.token);\n }\n\n async get<T>(path: string, query?: Record<string, string | number | boolean | undefined>): Promise<T> {\n const url = new URL(\n `${this.apiRoot}${path.startsWith('/') ? path : `/${path}`}`,\n typeof window !== 'undefined' ? window.location.origin : 'http://localhost',\n );\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null && value !== '') {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n const response = await fetch(url.toString(), {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n Authorization: `Bearer ${this.token}`,\n },\n });\n\n const bodyText = await response.text();\n if (!response.ok) {\n throw new JiraApiError(\n `Jira API request failed (${response.status} ${response.statusText})`,\n response.status,\n bodyText,\n );\n }\n\n if (isEmpty(bodyText)) {\n return {} as T;\n }\n\n try {\n return JSON.parse(bodyText) as T;\n } catch {\n throw new JiraApiError('Jira API returned invalid JSON', response.status, bodyText);\n }\n }\n}\n\n//#endregion\n\n//#region ---- Response Shapes ----\n\nexport type JiraProjectDto = {\n id: string;\n key: string;\n name: string;\n projectTypeKey?: string;\n style?: string;\n simplified?: boolean;\n lead?: { accountId?: string; displayName?: string };\n avatarUrls?: Record<string, string>;\n description?: string;\n};\n\nexport type JiraIssueTypeDto = {\n id: string;\n name: string;\n description?: string;\n subtask?: boolean;\n hierarchyLevel?: number;\n iconUrl?: string;\n};\n\nexport type JiraFieldDto = {\n id: string;\n name: string;\n custom: boolean;\n schema?: { type?: string; custom?: string };\n};\n\nexport type JiraProjectStatusDto = {\n id: string;\n name: string;\n statuses: Array<{\n id: string;\n name: string;\n statusCategory?: { key?: string };\n }>;\n};\n\nexport type JiraSearchResultDto = {\n issues?: Array<{\n id: string;\n key: string;\n fields?: Record<string, unknown>;\n }>;\n};\n\nexport type JiraWorklogListDto = {\n worklogs?: Array<{\n id: string;\n author?: { accountId?: string; displayName?: string };\n started: string;\n timeSpentSeconds: number;\n timeSpent?: string;\n comment?: string;\n created?: string;\n updated?: string;\n }>;\n};\n\nexport type JiraCreateMetaDto = {\n projects?: Array<{\n issuetypes?: Array<{\n id: string;\n fields?: Record<\n string,\n {\n required?: boolean;\n hasDefaultValue?: boolean;\n defaultValue?: unknown;\n allowedValues?: unknown[];\n schema?: { type?: string };\n }\n >;\n }>;\n }>;\n};\n\nexport function readIssueField<T>(issue: { fields?: Record<string, unknown> }, path: string): T | undefined {\n return get(issue.fields, path) as T | undefined;\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport {\n RootConfig,\n type AXMJiraManagementJiraInstanceEntityModel,\n} from '@acorex/modules/jira-management';\nimport { createMultiLanguageString } from '@acorex/platform/contracts';\nimport { AXPEntityStorageService } from '@acorex/platform/layout/entity';\nimport { AXPIntegrationRuntimeService } from '@acorex/platform/common';\nimport { inject, Injectable } from '@angular/core';\nimport { defaultTo, get, isString, trim } from 'lodash-es';\nimport {\n JiraApiClient,\n JiraApiError,\n readIssueField,\n type JiraCreateMetaDto,\n type JiraFieldDto,\n type JiraIssueTypeDto,\n type JiraProjectDto,\n type JiraProjectStatusDto,\n type JiraSearchResultDto,\n type JiraWorklogListDto,\n} from './jira-api.client';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface JiraInstanceSyncInput {\n instanceId: string;\n}\n\nexport interface JiraInstanceSyncResult {\n instanceId: string;\n projects: number;\n issueTypes: number;\n fields: number;\n workflowStatuses: number;\n projectIssueTypes: number;\n projectIssueTypeFields: number;\n issues: number;\n worklogs: number;\n}\n\ntype StoredRow = { id: string } & Record<string, unknown>;\n\n//#endregion\n\n//#region ---- Service ----\n\n@Injectable({ providedIn: 'root' })\nexport class AXCJiraInstanceSyncService {\n //#region ---- Services & Dependencies ----\n\n private readonly storage = inject(AXPEntityStorageService);\n private readonly integrationRuntime = inject(AXPIntegrationRuntimeService, { optional: true });\n\n private readonly instanceEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraInstance.name}`;\n private readonly projectEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProject.name}`;\n private readonly issueTypeEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraIssueType.name}`;\n private readonly fieldEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraField.name}`;\n private readonly projectIssueTypeEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProjectIssueType.name}`;\n private readonly projectIssueTypeFieldEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraProjectIssueTypeField.name}`;\n private readonly workflowStatusEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraWorkflowStatus.name}`;\n private readonly issueEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraIssue.name}`;\n private readonly worklogEntity = `${RootConfig.module.name}.${RootConfig.entities.jiraWorklog.name}`;\n\n //#endregion\n\n //#region ---- Public API ----\n\n async sync(input: JiraInstanceSyncInput): Promise<JiraInstanceSyncResult> {\n const instance = (await this.storage.getOne(this.instanceEntity, input.instanceId)) as\n | AXMJiraManagementJiraInstanceEntityModel\n | null;\n\n if (!instance) {\n throw new Error('Jira instance not found.');\n }\n\n const token = await this.resolveToken(instance);\n const baseUrl = defaultTo(trim(defaultTo(instance.baseUrl, '')), trim(defaultTo(instance.siteUrl, '')));\n if (!baseUrl) {\n throw new Error('Configure base URL before syncing.');\n }\n\n const client = new JiraApiClient({\n baseUrl,\n token,\n apiVersion: instance.apiVersion,\n });\n\n const [\n jiraProjects,\n jiraIssueTypes,\n jiraFields,\n existingProjects,\n existingIssueTypes,\n existingFields,\n existingProjectIssueTypes,\n existingProjectIssueTypeFields,\n existingWorkflowStatuses,\n existingIssues,\n existingWorklogs,\n ] = await Promise.all([\n client.get<JiraProjectDto[]>('/project'),\n client.get<JiraIssueTypeDto[]>('/issuetype'),\n client.get<JiraFieldDto[]>('/field'),\n this.loadAll(this.projectEntity),\n this.loadAll(this.issueTypeEntity),\n this.loadAll(this.fieldEntity),\n this.loadAll(this.projectIssueTypeEntity),\n this.loadAll(this.projectIssueTypeFieldEntity),\n this.loadAll(this.workflowStatusEntity),\n this.loadAll(this.issueEntity),\n this.loadAll(this.worklogEntity),\n ]);\n\n const instanceTitle = instance.title;\n const instanceName = instance.name;\n let projectIssueTypes = 0;\n let projectIssueTypeFields = 0;\n let workflowStatuses = 0;\n let issues = 0;\n let worklogs = 0;\n\n const issueTypeIdByJiraId = new Map<string, string>();\n\n for (const jiraIssueType of jiraIssueTypes) {\n const id = await this.upsertRow(\n this.issueTypeEntity,\n existingIssueTypes,\n (row) => row['jiraInstanceId'] === instance.id && row['jiraIssueTypeId'] === jiraIssueType.id,\n {\n jiraInstanceId: instance.id,\n jiraInstance: { id: instance.id, title: instanceTitle },\n jiraIssueTypeId: jiraIssueType.id,\n name: jiraIssueType.name,\n description: jiraIssueType.description ? createMultiLanguageString(jiraIssueType.description) : null,\n subtask: jiraIssueType.subtask === true,\n hierarchyLevel: defaultTo(jiraIssueType.hierarchyLevel, 0),\n iconUrl: jiraIssueType.iconUrl ?? null,\n },\n );\n issueTypeIdByJiraId.set(jiraIssueType.id, id);\n }\n\n const fieldIdByJiraFieldId = new Map<string, string>();\n for (const jiraField of jiraFields) {\n const fieldId = await this.upsertRow(\n this.fieldEntity,\n existingFields,\n (row) => row['jiraInstanceId'] === instance.id && row['jiraFieldId'] === jiraField.id,\n {\n jiraInstanceId: instance.id,\n jiraInstance: { id: instance.id, name: instanceName },\n jiraFieldId: jiraField.id,\n name: jiraField.name,\n custom: jiraField.custom === true,\n fieldType: get(jiraField, 'schema.type') ?? null,\n schema: get(jiraField, 'schema.custom') ?? null,\n },\n );\n fieldIdByJiraFieldId.set(jiraField.id, fieldId);\n }\n\n const projectIdByJiraId = new Map<string, string>();\n for (const jiraProject of jiraProjects) {\n const projectId = await this.upsertRow(\n this.projectEntity,\n existingProjects,\n (row) => row['jiraInstanceId'] === instance.id && row['jiraProjectId'] === jiraProject.id,\n {\n jiraInstanceId: instance.id,\n jiraInstance: { id: instance.id, title: instanceTitle, name: instanceName },\n jiraProjectId: jiraProject.id,\n key: jiraProject.key,\n name: jiraProject.name,\n projectTypeKey: jiraProject.projectTypeKey ?? null,\n style: jiraProject.style ?? null,\n simplified: jiraProject.simplified ?? null,\n leadAccountId: jiraProject.lead?.accountId ?? null,\n leadDisplayName: jiraProject.lead?.displayName ?? null,\n avatarUrl: jiraProject.avatarUrls?.['48x48'] ?? null,\n description: jiraProject.description ? createMultiLanguageString(jiraProject.description) : null,\n projectStatusId: 'Active',\n },\n );\n projectIdByJiraId.set(jiraProject.id, projectId);\n\n const statusesByIssueType = await client.get<JiraProjectStatusDto[]>(`/project/${jiraProject.key}/statuses`);\n const linkedIssueTypeIds = new Set<string>();\n\n for (const issueTypeBlock of statusesByIssueType) {\n const localIssueTypeId = issueTypeIdByJiraId.get(issueTypeBlock.id);\n if (!localIssueTypeId) {\n continue;\n }\n\n linkedIssueTypeIds.add(localIssueTypeId);\n await this.upsertRow(\n this.projectIssueTypeEntity,\n existingProjectIssueTypes,\n (row) => row['projectId'] === projectId && row['issueTypeId'] === localIssueTypeId,\n {\n projectId,\n project: { id: projectId, key: jiraProject.key, name: jiraProject.name },\n issueTypeId: localIssueTypeId,\n issueType: { id: localIssueTypeId, name: issueTypeBlock.name },\n },\n );\n projectIssueTypes += 1;\n\n let order = 0;\n for (const status of issueTypeBlock.statuses) {\n order += 1;\n await this.upsertRow(\n this.workflowStatusEntity,\n existingWorkflowStatuses,\n (row) =>\n row['projectId'] === projectId &&\n row['issueTypeId'] === localIssueTypeId &&\n row['jiraStatusId'] === status.id,\n {\n projectId,\n project: { id: projectId, key: jiraProject.key, name: jiraProject.name },\n issueTypeId: localIssueTypeId,\n issueType: { id: localIssueTypeId, name: issueTypeBlock.name },\n jiraStatusId: status.id,\n name: status.name,\n statusCategoryKey: this.mapStatusCategory(status.statusCategory?.key),\n order,\n },\n );\n workflowStatuses += 1;\n }\n }\n\n const createMeta = await client.get<JiraCreateMetaDto>('/issue/createmeta', {\n projectKeys: jiraProject.key,\n expand: 'projects.issuetypes.fields',\n });\n\n for (const projectMeta of createMeta.projects ?? []) {\n for (const issueTypeMeta of projectMeta.issuetypes ?? []) {\n const localIssueTypeId = issueTypeIdByJiraId.get(issueTypeMeta.id);\n if (!localIssueTypeId || !linkedIssueTypeIds.has(localIssueTypeId)) {\n continue;\n }\n\n let fieldOrder = 0;\n for (const [jiraFieldKey, fieldMeta] of Object.entries(issueTypeMeta.fields ?? {})) {\n const localFieldId = fieldIdByJiraFieldId.get(jiraFieldKey);\n if (!localFieldId) {\n continue;\n }\n\n fieldOrder += 1;\n await this.upsertRow(\n this.projectIssueTypeFieldEntity,\n existingProjectIssueTypeFields,\n (row) =>\n row['projectId'] === projectId &&\n row['issueTypeId'] === localIssueTypeId &&\n row['fieldId'] === localFieldId,\n {\n projectId,\n project: { id: projectId, key: jiraProject.key, name: jiraProject.name },\n issueTypeId: localIssueTypeId,\n issueType: { id: localIssueTypeId, name: issueTypeBlockName(issueTypeMeta.id, statusesByIssueType) },\n fieldId: localFieldId,\n field: { id: localFieldId, jiraFieldId: jiraFieldKey, name: jiraFieldKey },\n required: fieldMeta.required === true,\n hasDefaultValue: fieldMeta.hasDefaultValue === true,\n defaultValue: fieldMeta.defaultValue != null ? JSON.stringify(fieldMeta.defaultValue) : null,\n allowedValues:\n fieldMeta.allowedValues && fieldMeta.allowedValues.length > 0\n ? JSON.stringify(fieldMeta.allowedValues)\n : null,\n order: fieldOrder,\n },\n );\n projectIssueTypeFields += 1;\n }\n }\n }\n\n const search = await client.get<JiraSearchResultDto>('/search', {\n jql: `project = ${jiraProject.key} ORDER BY updated DESC`,\n maxResults: 50,\n fields: 'summary,description,issuetype,status,assignee,reporter,priority,parent,resolution,labels,created,updated',\n });\n\n for (const jiraIssue of search.issues ?? []) {\n const jiraIssueTypeId = readIssueField<{ id?: string }>(jiraIssue, 'issuetype.id')?.id;\n const jiraStatusId = readIssueField<{ id?: string }>(jiraIssue, 'status.id')?.id;\n const localIssueTypeId = jiraIssueTypeId ? issueTypeIdByJiraId.get(jiraIssueTypeId) : undefined;\n\n const workflowStatus = existingWorkflowStatuses.find(\n (row) =>\n row['projectId'] === projectId &&\n row['issueTypeId'] === localIssueTypeId &&\n row['jiraStatusId'] === jiraStatusId,\n );\n\n const parentJiraId = readIssueField<{ id?: string }>(jiraIssue, 'parent.id')?.id;\n const parentIssue = parentJiraId\n ? existingIssues.find((row) => row['jiraIssueId'] === parentJiraId)\n : undefined;\n\n const issueId = await this.upsertRow(\n this.issueEntity,\n existingIssues,\n (row) => row['jiraInstanceId'] === instance.id && row['jiraIssueId'] === jiraIssue.id,\n {\n jiraInstanceId: instance.id,\n jiraInstance: { id: instance.id, name: instanceName },\n projectId,\n project: { id: projectId, key: jiraProject.key, name: jiraProject.name },\n issueTypeId: localIssueTypeId ?? '',\n issueType: localIssueTypeId\n ? { id: localIssueTypeId, name: readIssueField<{ name?: string }>(jiraIssue, 'issuetype.name')?.name }\n : undefined,\n workflowStatusId: workflowStatus?.id ?? '',\n workflowStatus: workflowStatus\n ? {\n id: workflowStatus.id,\n name: workflowStatus['name'] as string,\n statusCategoryKey: workflowStatus['statusCategoryKey'] as string,\n }\n : undefined,\n jiraIssueId: jiraIssue.id,\n jiraIssueKey: jiraIssue.key,\n summary: defaultTo(readIssueField<string>(jiraIssue, 'summary'), jiraIssue.key),\n description: readIssueField<string>(jiraIssue, 'description') ?? null,\n assigneeAccountId: readIssueField<{ accountId?: string }>(jiraIssue, 'assignee.accountId')?.accountId ?? null,\n assigneeDisplayName:\n readIssueField<{ displayName?: string }>(jiraIssue, 'assignee.displayName')?.displayName ?? null,\n reporterAccountId: readIssueField<{ accountId?: string }>(jiraIssue, 'reporter.accountId')?.accountId ?? null,\n reporterDisplayName:\n readIssueField<{ displayName?: string }>(jiraIssue, 'reporter.displayName')?.displayName ?? null,\n priorityName: readIssueField<{ name?: string }>(jiraIssue, 'priority.name')?.name ?? null,\n parentIssueId: parentIssue?.id ?? null,\n parentIssue: parentIssue\n ? { id: parentIssue.id, jiraIssueKey: parentIssue['jiraIssueKey'] as string }\n : undefined,\n resolutionName: readIssueField<{ name?: string }>(jiraIssue, 'resolution.name')?.name ?? null,\n labels: JSON.stringify(readIssueField<string[]>(jiraIssue, 'labels') ?? []),\n jiraCreated: readIssueField<string>(jiraIssue, 'created') ?? null,\n jiraUpdated: readIssueField<string>(jiraIssue, 'updated') ?? null,\n },\n );\n issues += 1;\n\n const worklogList = await client.get<JiraWorklogListDto>(`/issue/${jiraIssue.key}/worklog`);\n for (const worklog of worklogList.worklogs ?? []) {\n await this.upsertRow(\n this.worklogEntity,\n existingWorklogs,\n (row) => row['issueId'] === issueId && row['jiraWorklogId'] === worklog.id,\n {\n issueId,\n issue: { id: issueId, jiraIssueKey: jiraIssue.key, summary: readIssueField<string>(jiraIssue, 'summary') },\n jiraWorklogId: worklog.id,\n authorAccountId: worklog.author?.accountId ?? null,\n authorDisplayName: worklog.author?.displayName ?? null,\n started: worklog.started,\n timeSpentSeconds: worklog.timeSpentSeconds,\n timeSpentDisplay: worklog.timeSpent ?? null,\n comment: isString(worklog.comment) ? worklog.comment : null,\n jiraCreated: worklog.created ?? null,\n jiraUpdated: worklog.updated ?? null,\n },\n );\n worklogs += 1;\n }\n }\n }\n\n await this.storage.updateOne(this.instanceEntity, instance.id, {\n lastSyncAt: new Date().toISOString(),\n });\n\n return {\n instanceId: instance.id,\n projects: jiraProjects.length,\n issueTypes: jiraIssueTypes.length,\n fields: jiraFields.length,\n workflowStatuses,\n projectIssueTypes,\n projectIssueTypeFields,\n issues,\n worklogs,\n };\n }\n\n //#endregion\n\n //#region ---- Utility Methods ----\n\n private async resolveToken(instance: AXMJiraManagementJiraInstanceEntityModel): Promise<string> {\n if (instance.integrationConnectionId && this.integrationRuntime) {\n const client = await this.integrationRuntime.withClient(\n { providerId: 'jira', connectionScope: 'tenant', connectionKey: instance.name },\n async (resolved) => resolved as { token: string },\n );\n const token = trim(defaultTo(client.token, ''));\n if (token) {\n return token;\n }\n }\n\n const adminToken = trim(defaultTo(instance.adminToken, ''));\n if (adminToken) {\n return adminToken;\n }\n\n const pat = trim(defaultTo(instance.personalAccessToken, ''));\n if (pat) {\n return pat;\n }\n\n throw new Error('Configure an integration connection or personal access token before syncing.');\n }\n\n private async loadAll(entityName: string): Promise<StoredRow[]> {\n const result = await this.storage.query(entityName, { skip: 0, take: 50_000 });\n return (result.items ?? []) as StoredRow[];\n }\n\n private async upsertRow(\n entityName: string,\n cache: StoredRow[],\n match: (row: StoredRow) => boolean,\n payload: Record<string, unknown>,\n ): Promise<string> {\n const existing = cache.find(match);\n if (existing) {\n await this.storage.updateOne(entityName, existing.id, payload);\n Object.assign(existing, payload);\n return existing.id;\n }\n\n const id = crypto.randomUUID();\n await this.storage.insertOne(entityName, { id, ...payload });\n const created = { id, ...payload };\n cache.push(created);\n return id;\n }\n\n private mapStatusCategory(key?: string): 'new' | 'indeterminate' | 'done' {\n if (key === 'done') {\n return 'done';\n }\n if (key === 'indeterminate') {\n return 'indeterminate';\n }\n return 'new';\n }\n\n //#endregion\n}\n\nfunction issueTypeBlockName(issueTypeId: string, blocks: JiraProjectStatusDto[]): string {\n return blocks.find((block) => block.id === issueTypeId)?.name ?? issueTypeId;\n}\n\nexport { JiraApiError };\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXPCommand } from '@acorex/platform/runtime-contracts';\nimport { AXLoadingDialogService } from '@acorex/components/loading-dialog';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { RootConfig } from '@acorex/modules/jira-management';\nimport { AXPExecuteCommandResult } from '@acorex/platform/contracts';\n\nimport { inject, Injectable } from '@angular/core';\nimport { defaultTo, get } from 'lodash-es';\nimport { AXCJiraInstanceSyncService, JiraApiError, type JiraInstanceSyncResult } from './jira-instance-sync.service';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface JiraInstanceSyncCommandInput {\n instanceId?: string;\n}\n\nconst I18N = `${RootConfig.config.i18n}:instances.entities.instance`;\n\n//#endregion\n\n//#region ---- Command ----\n\n@Injectable({ providedIn: 'root' })\nexport class AXCJiraInstanceSyncCommand implements AXPCommand<JiraInstanceSyncCommandInput, JiraInstanceSyncResult> {\n //#region ---- Services & Dependencies ----\n\n private readonly syncService = inject(AXCJiraInstanceSyncService);\n private readonly loadingDialog = inject(AXLoadingDialogService);\n private readonly translation = inject(AXTranslationService);\n\n //#endregion\n\n //#region ---- Command Execution ----\n\n async execute(input?: JiraInstanceSyncCommandInput): Promise<AXPExecuteCommandResult<JiraInstanceSyncResult>> {\n const instanceId = defaultTo(get(input, 'instanceId'), '').trim();\n if (!instanceId) {\n return {\n success: false,\n message: {\n text: await this.translation.translateAsync(`@${I18N}.actions.sync.messages.missing-instance`),\n },\n };\n }\n\n const [loadingTitle, loadingDescription] = await Promise.all([\n this.translation.translateAsync(`@${I18N}.actions.sync.loading.title`),\n this.translation.translateAsync(`@${I18N}.actions.sync.loading.description`),\n ]);\n\n const progressDialog = this.loadingDialog.show({\n title: loadingTitle,\n mode: 'indeterminate',\n progressColor: 'primary',\n text: loadingDescription,\n });\n\n try {\n const data = await this.syncService.sync({ instanceId });\n return {\n success: true,\n data,\n message: {\n text: await this.translation.translateAsync(`@${I18N}.actions.sync.messages.success`, {\n params: {\n projects: data.projects,\n issues: data.issues,\n },\n }),\n },\n };\n } catch (error) {\n const fallback = await this.translation.translateAsync(`@${I18N}.actions.sync.messages.failed`);\n let text = error instanceof Error ? error.message : fallback;\n if (error instanceof JiraApiError && error.status === 0) {\n text = await this.translation.translateAsync(`@${I18N}.actions.sync.messages.network-error`);\n }\n return {\n success: false,\n message: { text },\n };\n } finally {\n progressDialog.close();\n }\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { AXPDataGenerator } from '@acorex/platform/contracts';
2
+ import { AXToastService } from '@acorex/components/toast';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, Injectable } from '@angular/core';
5
+
6
+ //#endregion
7
+ //#region ---- Input parsing ----
8
+ function parseSendInput(raw) {
9
+ const obj = raw != null && typeof raw === 'object' && !Array.isArray(raw) ? raw : null;
10
+ if (!obj) {
11
+ return { ok: false, error: 'Invalid arguments: expected an object.' };
12
+ }
13
+ const to = typeof obj['to'] === 'string' ? obj['to'].trim() : '';
14
+ const subject = typeof obj['subject'] === 'string' ? obj['subject'].trim() : '';
15
+ const body = typeof obj['body'] === 'string' ? obj['body'].trim() : '';
16
+ if (!to) {
17
+ return { ok: false, error: 'Invalid arguments: "to" is required.' };
18
+ }
19
+ if (!subject) {
20
+ return { ok: false, error: 'Invalid arguments: "subject" is required.' };
21
+ }
22
+ if (!body) {
23
+ return { ok: false, error: 'Invalid arguments: "body" is required.' };
24
+ }
25
+ const cc = typeof obj['cc'] === 'string' ? obj['cc'].trim() : '';
26
+ const bcc = typeof obj['bcc'] === 'string' ? obj['bcc'].trim() : '';
27
+ const tid = typeof obj['textTemplateId'] === 'string' ? obj['textTemplateId'].trim() : '';
28
+ return {
29
+ ok: true,
30
+ value: {
31
+ to,
32
+ subject,
33
+ body,
34
+ ...(cc ? { cc } : {}),
35
+ ...(bcc ? { bcc } : {}),
36
+ ...(tid ? { textTemplateId: tid } : {}),
37
+ },
38
+ };
39
+ }
40
+ //#endregion
41
+ //#region ---- Mock send command ----
42
+ const MOCK_SEND_LATENCY_MS = 120;
43
+ class NotificationManagementEmailSendMockCommand {
44
+ constructor() {
45
+ this.toastService = inject(AXToastService);
46
+ }
47
+ async execute(input) {
48
+ await new Promise((resolve) => setTimeout(resolve, MOCK_SEND_LATENCY_MS));
49
+ const parsed = parseSendInput(input);
50
+ if (!parsed.ok) {
51
+ return { success: false, message: { text: parsed.error } };
52
+ }
53
+ // Mock transport: surface as UI toast only; replace with HTTP when backend exists.
54
+ this.toastService.show({
55
+ color: 'warning',
56
+ title: 'Email send (simulation)',
57
+ content: `No email was delivered — mock only.\n To: ${parsed.value.to}.\n Subject: ${parsed.value.subject}.`,
58
+ });
59
+ return {
60
+ success: true,
61
+ data: { messageId: AXPDataGenerator.uuid() },
62
+ };
63
+ }
64
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationManagementEmailSendMockCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
65
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationManagementEmailSendMockCommand }); }
66
+ }
67
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationManagementEmailSendMockCommand, decorators: [{
68
+ type: Injectable
69
+ }] });
70
+
71
+ export { NotificationManagementEmailSendMockCommand };
72
+ //# sourceMappingURL=acorex-connectivity-mock-notification-management-email-send.command-BuH_Lm6V.mjs.map