complexqa_frontend_core 1.24.1 → 1.26.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 (26) hide show
  1. package/package.json +1 -1
  2. package/publish/api/attachment_api.js +55 -0
  3. package/publish/api/file_app_api.js +22 -0
  4. package/publish/api/index.js +6 -0
  5. package/publish/api/team_domain_api.js +62 -0
  6. package/publish/api/team_management_api.js +1 -1
  7. package/publish/api/util/url_inspect_api.js +54 -0
  8. package/publish/app_configuration/table/helpers/table_element_models.js +6 -0
  9. package/publish/app_configuration/table/sections/team_domain.js +55 -0
  10. package/publish/app_configuration/table/sections/util_execution_url_inspect.js +60 -0
  11. package/publish/app_configuration/table/table_configuration.js +4 -0
  12. package/publish/index.js +4 -0
  13. package/publish/services/FileAppService.js +67 -21
  14. package/publish/types/element_translate/typeAttachment.i18n.js +201 -0
  15. package/publish/types/element_translate/typeTeamDomain.i18n.js +71 -0
  16. package/publish/types/element_translate/typeTeamTotalStatistic.i18n.js +210 -67
  17. package/publish/types/element_translate/typeUtilExecutionUrlInspect.i18n.js +55 -0
  18. package/publish/types/element_translate/typeUtilExecutionUrlInspectCheck.i18n.js +111 -0
  19. package/publish/types/family_contracts/typeTeamTotalStatistic.js +6 -10
  20. package/publish/types/family_elements/typeAttachment.js +119 -0
  21. package/publish/types/family_elements/typeTeam.js +5 -2
  22. package/publish/types/family_elements/typeTeamDomain.js +172 -0
  23. package/publish/types/family_events/familyEvent.js +1 -0
  24. package/publish/types/family_files/typeFileScreenshot.js +2 -2
  25. package/publish/types/family_utils/typeUtilExecutionUrlInspect.js +199 -0
  26. package/publish/types/family_utils/typeUtilExecutionUrlInspectCheck.js +100 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Переводы для typeUtilExecutionUrlInspectCheck.
3
+ *
4
+ * @see typeUtilExecutionUrlInspectCheck
5
+ */
6
+ export const typeUtilExecutionUrlInspectCheck_i18n = {
7
+ attribute_name_translate_matrix: {
8
+ en: {
9
+ url_inspect_check_id: 'Check',
10
+ util_execution_id : 'Run',
11
+ sort_order : 'Order',
12
+ check_kind : 'Kind',
13
+ check_status : 'Status',
14
+ finding_code : 'Finding',
15
+ summary_message : 'Summary',
16
+ detail_message : 'Detail',
17
+ },
18
+ ru: {
19
+ url_inspect_check_id: 'Проверка',
20
+ util_execution_id : 'Запуск',
21
+ sort_order : 'Порядок',
22
+ check_kind : 'Вид',
23
+ check_status : 'Статус',
24
+ finding_code : 'Находка',
25
+ summary_message : 'Кратко',
26
+ detail_message : 'Подробности',
27
+ },
28
+ },
29
+ enum_value_translate_matrix: {
30
+ check_kind: {
31
+ en: {
32
+ DNS : 'DNS',
33
+ TCP_80 : 'TCP 80',
34
+ TCP_443 : 'TCP 443',
35
+ TLS : 'TLS',
36
+ HTTP : 'HTTP',
37
+ HTTPS : 'HTTPS',
38
+ SECURITY_HEADERS: 'Security headers',
39
+ BROWSER : 'Browser',
40
+ },
41
+ ru: {
42
+ DNS : 'DNS',
43
+ TCP_80 : 'TCP 80',
44
+ TCP_443 : 'TCP 443',
45
+ TLS : 'TLS',
46
+ HTTP : 'HTTP',
47
+ HTTPS : 'HTTPS',
48
+ SECURITY_HEADERS: 'Заголовки безопасности',
49
+ BROWSER : 'Браузер',
50
+ },
51
+ },
52
+ check_status: {
53
+ en: {
54
+ PENDING : 'Pending',
55
+ QUEUED : 'Queued',
56
+ RUNNING : 'Running',
57
+ COMPLETED: 'Completed',
58
+ SKIPPED : 'Skipped',
59
+ ERROR : 'Error',
60
+ },
61
+ ru: {
62
+ PENDING : 'Ожидает',
63
+ QUEUED : 'В очереди',
64
+ RUNNING : 'Выполняется',
65
+ COMPLETED: 'Завершена',
66
+ SKIPPED : 'Пропущена',
67
+ ERROR : 'Ошибка',
68
+ },
69
+ },
70
+ finding_code: {
71
+ en: {
72
+ SUCCESS : 'Success',
73
+ ERR_NAME_NOT_RESOLVED : 'Name not resolved',
74
+ ERR_CONNECTION_REFUSED : 'Connection refused',
75
+ ERR_CONNECTION_TIMED_OUT : 'Connection timed out',
76
+ ERR_CERT_DATE_INVALID : 'Certificate date invalid',
77
+ ERR_CERT_AUTHORITY_INVALID : 'Certificate authority invalid',
78
+ ERR_CERT_COMMON_NAME_INVALID: 'Certificate name invalid',
79
+ ERR_SSL_PROTOCOL_ERROR : 'TLS protocol error',
80
+ ERR_TOO_MANY_REDIRECTS : 'Too many redirects',
81
+ HTTP_STATUS : 'HTTP status',
82
+ NO_TLS : 'No TLS',
83
+ EMPTY_BODY : 'Empty body',
84
+ PROTOTYPE_BROWSER_SKIPPED : 'Browser skipped (prototype)',
85
+ NO_PUBLIC_ADDRESS : 'No public address',
86
+ UNKNOWN_CHECK_KIND : 'Unknown check kind',
87
+ BROWSER_FAILED : 'Browser failed',
88
+ BROWSER_SUBMIT_FAILED : 'Browser submit failed',
89
+ },
90
+ ru: {
91
+ SUCCESS : 'Успех',
92
+ ERR_NAME_NOT_RESOLVED : 'Имя не резолвится',
93
+ ERR_CONNECTION_REFUSED : 'Соединение отклонено',
94
+ ERR_CONNECTION_TIMED_OUT : 'Таймаут соединения',
95
+ ERR_CERT_DATE_INVALID : 'Срок сертификата недействителен',
96
+ ERR_CERT_AUTHORITY_INVALID : 'Центр сертификации не принят',
97
+ ERR_CERT_COMMON_NAME_INVALID: 'Имя в сертификате не совпадает',
98
+ ERR_SSL_PROTOCOL_ERROR : 'Ошибка протокола TLS',
99
+ ERR_TOO_MANY_REDIRECTS : 'Слишком много редиректов',
100
+ HTTP_STATUS : 'HTTP-статус',
101
+ NO_TLS : 'Нет TLS',
102
+ EMPTY_BODY : 'Пустое тело',
103
+ PROTOTYPE_BROWSER_SKIPPED : 'Браузер пропущен (прототип)',
104
+ NO_PUBLIC_ADDRESS : 'Нет публичного адреса',
105
+ UNKNOWN_CHECK_KIND : 'Неизвестный вид проверки',
106
+ BROWSER_FAILED : 'Ошибка браузера',
107
+ BROWSER_SUBMIT_FAILED : 'Не удалось поставить браузер в очередь',
108
+ },
109
+ },
110
+ },
111
+ };
@@ -2,19 +2,15 @@ import { familyContracts } from "./familyContracts.js";
2
2
  import { typeTeamTotalStatistic_i18n } from "../element_translate/typeTeamTotalStatistic.i18n.js";
3
3
 
4
4
  /**
5
+ * Translation contract for team total_usage rows
6
+ * (`element_model` / `util_action_key` labels).
5
7
  *
6
- * @version v.1.0 (31/03/2026)
8
+ * API row: { kind, element_model, count, price_limit }
9
+ *
10
+ * @version v.1.1 (14/08/2026)
7
11
  */
8
12
  export class typeTeamTotalStatistic extends familyContracts
9
13
  {
10
- project;
11
- test_suite;
12
- test_case;
13
- test_case_step;
14
- test_run;
15
- team_member;
16
-
17
-
18
14
  attribute_name_translate_matrix = typeTeamTotalStatistic_i18n.attribute_name_translate_matrix;
19
15
 
20
- }
16
+ }
@@ -0,0 +1,119 @@
1
+ import { familyGeneralElement } from "../core/0_familyGeneralElement.js";
2
+ import { is_object } from "../../utils/utils.js";
3
+ import _ from 'underscore';
4
+ import { typeAttachment_i18n } from "../element_translate/typeAttachment.i18n.js";
5
+
6
+ /**
7
+ * First-class link entity: element ↔ File App file (`file_uuid`).
8
+ *
9
+ * Not a family_relation — polymorphic target via `element_type` + `element_id`,
10
+ * file identity via public `file_uuid` (not File App internal `file_id`).
11
+ *
12
+ * @see docs/Attachments/attachment-docs.MD
13
+ *
14
+ * @version v.0.1 (13/08/2026)
15
+ */
16
+ export class typeAttachment extends familyGeneralElement
17
+ {
18
+ attachment_id;
19
+ team_id;
20
+ project_id;
21
+ element_type;
22
+ element_id;
23
+ file_uuid;
24
+ caption;
25
+ sort_order;
26
+ user_id;
27
+ created_at;
28
+ updated_at;
29
+
30
+ /** Hydrated via search options.add: ['files'] */
31
+ file;
32
+
33
+ primary_key = 'attachment_id';
34
+ api_key = 'attachment';
35
+
36
+ structure_scheme = {
37
+ attachment_id: 'integer | require',
38
+ team_id : 'integer | require',
39
+ project_id : 'integer | require',
40
+ element_type : 'string | enum | require',
41
+ element_id : 'integer | require',
42
+ file_uuid : 'string | require',
43
+ caption : 'string | optional',
44
+ sort_order : 'integer | optional',
45
+ user_id : 'integer | optional',
46
+ created_at : 'timestamp | optional',
47
+ updated_at : 'timestamp | optional',
48
+ };
49
+
50
+ create_scheme = [
51
+ 'project_id',
52
+ 'element_type',
53
+ 'element_id',
54
+ 'file_uuid',
55
+ 'caption',
56
+ 'sort_order',
57
+ ];
58
+
59
+ available_enum_values = {
60
+ element_type: typeAttachment.get_element_type_values(),
61
+ };
62
+
63
+ enum_value_translate_matrix = typeAttachment_i18n.enum_value_translate_matrix;
64
+
65
+ attribute_name_translate_matrix = typeAttachment_i18n.attribute_name_translate_matrix;
66
+
67
+
68
+ /**
69
+ * Canonical element_type values (WITHOUT `_id` suffix). MVP: bug only.
70
+ *
71
+ * @returns {string[]}
72
+ */
73
+ static get_element_type_values()
74
+ {
75
+ return [ 'bug' ];
76
+ }
77
+
78
+
79
+ /**
80
+ * @param {object|false|undefined} data
81
+ * @returns {typeAttachment}
82
+ */
83
+ constructor(data = false)
84
+ {
85
+ super();
86
+
87
+ if (data && is_object(data))
88
+ {
89
+ _.mapObject(data, (value, key) =>
90
+ {
91
+ if (this.hasOwnProperty(key))
92
+ {
93
+ this[ key ] = value;
94
+ }
95
+ });
96
+ }
97
+
98
+ return this;
99
+ }
100
+
101
+
102
+ /**
103
+ * @returns {string}
104
+ */
105
+ get_element_name()
106
+ {
107
+ if (this.caption)
108
+ {
109
+ return String(this.caption);
110
+ }
111
+
112
+ if (this.file_uuid)
113
+ {
114
+ return String(this.file_uuid);
115
+ }
116
+
117
+ return String(this.attachment_id ?? '');
118
+ }
119
+ }
@@ -107,9 +107,12 @@ export class typeTeam extends familyGeneralElement
107
107
 
108
108
 
109
109
  /**
110
- * Return {"project":1,"test_suite":1,"test_case":1,"test_case_step":1,"test_runs":1,"team_member":1}
110
+ * Billing catalog usage for the current team.
111
111
  *
112
- * @version v.0.1 (21/03/2026)
112
+ * Rows: [{ kind, element_model, count, price_limit }, ...]
113
+ * kind = entity | util; price_limit null = unlimited.
114
+ *
115
+ * @version v.0.2 (14/08/2026)
113
116
  * @returns {Promise<object>}
114
117
  */
115
118
  async get_team_total_statistic()
@@ -0,0 +1,172 @@
1
+ import { familyGeneralElement } from "../core/0_familyGeneralElement.js";
2
+ import { echo, is_object } from "../../utils/utils.js";
3
+ import { typeTeamDomain_i18n } from "../element_translate/typeTeamDomain.i18n.js";
4
+
5
+
6
+ /**
7
+ * Team-owned domain (cqa_team.team_domains). Shared across projects of the team.
8
+ * Verify/revoke via ApiService.team_domain; url.inspect requires VERIFIED.
9
+ * Backend: test_site/docs/team/team-domains.md
10
+ *
11
+ * @version v.0.1 (14/08/2026)
12
+ */
13
+ export class typeTeamDomain extends familyGeneralElement
14
+ {
15
+ team_domain_id;
16
+ team_id;
17
+ domain_canon;
18
+ display_name;
19
+ verification_method;
20
+ domain_status;
21
+ verification_token;
22
+ last_error_message;
23
+ verified_at;
24
+ created_at;
25
+ updated_at;
26
+ file_url_https;
27
+ file_url_http;
28
+ file_body;
29
+ dns_host;
30
+ dns_txt_value;
31
+ instruction;
32
+
33
+ primary_key = 'team_domain_id';
34
+ api_key = 'team_domain';
35
+
36
+ structure_scheme = {
37
+ team_domain_id : 'integer | optional',
38
+ team_id : 'integer | optional',
39
+ domain_canon : 'string | max:255 | require',
40
+ display_name : 'string | max:255 | optional',
41
+ verification_method: 'string | enum | require',
42
+ domain_status : 'string | enum | optional',
43
+ verification_token : 'string | optional',
44
+ last_error_message : 'string | optional',
45
+ verified_at : 'timestamp | optional',
46
+ created_at : 'timestamp | optional',
47
+ updated_at : 'timestamp | optional',
48
+ file_url_https : 'string | optional',
49
+ file_url_http : 'string | optional',
50
+ file_body : 'string | optional',
51
+ dns_host : 'string | optional',
52
+ dns_txt_value : 'string | optional',
53
+ instruction : 'string | optional',
54
+ };
55
+
56
+ create_scheme = [
57
+ 'domain_canon',
58
+ 'display_name',
59
+ 'verification_method',
60
+ ];
61
+
62
+ available_enum_values = {
63
+ verification_method: [ 'FILE', 'DNS_TXT' ],
64
+ domain_status : [ 'PENDING', 'VERIFIED', 'FAILED', 'REVOKED' ],
65
+ };
66
+
67
+ enum_value_translate_matrix = typeTeamDomain_i18n.enum_value_translate_matrix;
68
+ attribute_name_translate_matrix = typeTeamDomain_i18n.attribute_name_translate_matrix;
69
+
70
+ status_color = {
71
+ PENDING : '#4D92FA',
72
+ VERIFIED: '#009688',
73
+ FAILED : '#E66565',
74
+ REVOKED : '#9E9E9E',
75
+ };
76
+
77
+ clone_element = false;
78
+ delete_mass = false;
79
+ update_properties = false;
80
+ update = false;
81
+ clone_element_mass = false;
82
+
83
+
84
+ /**
85
+ * @param {object|false|undefined} data
86
+ */
87
+ constructor(data = false)
88
+ {
89
+ super();
90
+
91
+ if (data && is_object(data))
92
+ {
93
+ _.mapObject(data, (value, key) =>
94
+ {
95
+ if (this.hasOwnProperty(key))
96
+ {
97
+ this [ key ] = value;
98
+ }
99
+ });
100
+ }
101
+
102
+ return this;
103
+ }
104
+
105
+
106
+ /**
107
+ * @param {object} payload
108
+ * @param {object} callback
109
+ */
110
+ verify(payload, callback)
111
+ {
112
+ if (typeof callback?.before === 'function')
113
+ {
114
+ callback?.before({ payload });
115
+ }
116
+
117
+ return ApiService[ this.api_key ].verify(payload).then((response) =>
118
+ {
119
+ if (typeof callback?.success === 'function')
120
+ {
121
+ callback?.success({ response, payload });
122
+ }
123
+ }).catch((error) =>
124
+ {
125
+ echo({ error });
126
+ if (typeof callback?.error === 'function')
127
+ {
128
+ callback?.error({ error, payload });
129
+ }
130
+ }).finally((response) =>
131
+ {
132
+ if (typeof callback?.final === 'function')
133
+ {
134
+ callback?.final({ response, payload });
135
+ }
136
+ });
137
+ }
138
+
139
+
140
+ /**
141
+ * @param {object} payload
142
+ * @param {object} callback
143
+ */
144
+ revoke(payload, callback)
145
+ {
146
+ if (typeof callback?.before === 'function')
147
+ {
148
+ callback?.before({ payload });
149
+ }
150
+
151
+ return ApiService[ this.api_key ].revoke(payload).then((response) =>
152
+ {
153
+ if (typeof callback?.success === 'function')
154
+ {
155
+ callback?.success({ response, payload });
156
+ }
157
+ }).catch((error) =>
158
+ {
159
+ echo({ error });
160
+ if (typeof callback?.error === 'function')
161
+ {
162
+ callback?.error({ error, payload });
163
+ }
164
+ }).finally((response) =>
165
+ {
166
+ if (typeof callback?.final === 'function')
167
+ {
168
+ callback?.final({ response, payload });
169
+ }
170
+ });
171
+ }
172
+ }
@@ -58,6 +58,7 @@ export class familyEvent extends familyGeneralElement
58
58
  'task',
59
59
  'bug',
60
60
  'bug_relation',
61
+ 'attachment',
61
62
  'tag',
62
63
  'tag_relation',
63
64
  'test_account',
@@ -21,8 +21,8 @@ export class typeFileScreenshot extends typeFile
21
21
  *
22
22
  * @param {object} payload
23
23
  * @param {File|Blob} payload.file
24
- * @param {string} payload.entity_type
25
- * @param {number} payload.entity_id
24
+ * @param {string} [payload.entity_type] — omit / null / 0 for unbound upload (attachments)
25
+ * @param {number} [payload.entity_id] — omit / null / 0 for unbound upload (attachments)
26
26
  * @param {string} [payload.original_name]
27
27
  *
28
28
  * @returns {Promise<typeFileScreenshot>}
@@ -0,0 +1,199 @@
1
+ import { familyUtil } from "./familyUtil.js";
2
+ import { is_object } from "../../utils/utils.js";
3
+ import { typeUtilExecutionUrlInspect_i18n } from "../element_translate/typeUtilExecutionUrlInspect.i18n.js";
4
+ import { typeUtilExecutionUrlInspectCheck } from "./typeUtilExecutionUrlInspectCheck.js";
5
+ import { familyUtil_i18n } from "../element_translate/_familyUtil.i18n.js";
6
+ import { create_type_file_from_wire } from "../family_files/typeFileFactory.js";
7
+
8
+
9
+ /**
10
+ * url.inspect suite — one "Check now" run (family of probes). Always has project_id.
11
+ * Create/details/search via ApiService.url_inspect, not browser_tools_* APIs.
12
+ * Backend: test_site/docs/util_service/api-url-inspect.md
13
+ *
14
+ * @version v.0.1 (14/08/2026)
15
+ */
16
+ export class typeUtilExecutionUrlInspect extends familyUtil
17
+ {
18
+ util_execution_id;
19
+ util_action_id;
20
+ util_action_key;
21
+ project_id;
22
+ user_id;
23
+ team_id;
24
+ execution_status;
25
+ error_message;
26
+ submitted_at;
27
+ completed_at;
28
+ created_at;
29
+ team_domain_id;
30
+ domain_canon;
31
+ page_path;
32
+ suite_status;
33
+ checks;
34
+ browser;
35
+
36
+ primary_key = 'util_execution_id';
37
+ api_key = 'url_inspect';
38
+
39
+ structure_scheme = {
40
+ util_execution_id: 'integer | optional',
41
+ util_action_id : 'integer | optional',
42
+ util_action_key : 'string | optional',
43
+ project_id : 'integer | require',
44
+ user_id : 'integer | optional',
45
+ team_id : 'integer | optional',
46
+ execution_status : 'string | enum | optional',
47
+ error_message : 'string | optional',
48
+ submitted_at : 'timestamp | optional',
49
+ completed_at : 'timestamp | optional',
50
+ created_at : 'timestamp | optional',
51
+ team_domain_id : 'integer | require',
52
+ domain_canon : 'string | optional',
53
+ page_path : 'string | optional',
54
+ suite_status : 'string | enum | optional',
55
+ };
56
+
57
+ create_scheme = [
58
+ 'project_id',
59
+ 'team_domain_id',
60
+ 'page_path',
61
+ ];
62
+
63
+ available_enum_values = {
64
+ execution_status: familyUtil.get_execution_status_values(),
65
+ suite_status : [ 'CREATED', 'QUEUED', 'RUNNING', 'COMPLETED', 'PARTIAL', 'FAILED', 'SUBMIT_FAILED' ],
66
+ };
67
+
68
+ enum_value_translate_matrix = {
69
+ ...typeUtilExecutionUrlInspect_i18n.enum_value_translate_matrix,
70
+ execution_status: familyUtil_i18n.execution_status,
71
+ };
72
+
73
+ attribute_name_translate_matrix = typeUtilExecutionUrlInspect_i18n.attribute_name_translate_matrix;
74
+
75
+ status_color = {
76
+ CREATED : '#4D92FA',
77
+ QUEUED : '#009688',
78
+ RUNNING : '#4D92FA',
79
+ COMPLETED : '#009688',
80
+ PARTIAL : '#F0A202',
81
+ FAILED : '#E66565',
82
+ SUBMIT_FAILED: '#E66565',
83
+ };
84
+
85
+ clone_element = false;
86
+ delete_mass = false;
87
+ update_properties = false;
88
+ update = false;
89
+ clone_element_mass = false;
90
+
91
+
92
+ /**
93
+ * @param {object|false|undefined} data
94
+ */
95
+ constructor(data = false)
96
+ {
97
+ super();
98
+
99
+ if (data && is_object(data))
100
+ {
101
+ _.mapObject(data, (value, key) =>
102
+ {
103
+ if (key === 'checks' && Array.isArray(value))
104
+ {
105
+ this.checks = value.map((row) => new typeUtilExecutionUrlInspectCheck(row));
106
+ }
107
+ else if (key === 'browser')
108
+ {
109
+ this.browser = typeUtilExecutionUrlInspect.hydrateBrowser(value);
110
+ }
111
+ else if (this.hasOwnProperty(key))
112
+ {
113
+ this [ key ] = value;
114
+ }
115
+ });
116
+ }
117
+
118
+ return this;
119
+ }
120
+
121
+
122
+ /**
123
+ * @param {object|false|undefined} data
124
+ *
125
+ * @returns {typeUtilExecutionUrlInspect|false}
126
+ */
127
+ static composeDetails(data)
128
+ {
129
+ if (!data || !is_object(data))
130
+ {
131
+ return false;
132
+ }
133
+
134
+ return new typeUtilExecutionUrlInspect(data);
135
+ }
136
+
137
+
138
+ /**
139
+ * @param {object|null|undefined} value
140
+ *
141
+ * @returns {object|null}
142
+ */
143
+ static hydrateBrowser(value)
144
+ {
145
+ if (!value || !is_object(value))
146
+ {
147
+ return null;
148
+ }
149
+
150
+ return {
151
+ ...value,
152
+ screenshot_file: value.screenshot_file
153
+ ? create_type_file_from_wire(value.screenshot_file)
154
+ : false,
155
+ har_file: value.har_file
156
+ ? create_type_file_from_wire(value.har_file)
157
+ : false,
158
+ console: Array.isArray(value.console) ? value.console : [],
159
+ mixed_content: Array.isArray(value.mixed_content) ? value.mixed_content : [],
160
+ screenshots: Array.isArray(value.screenshots)
161
+ ? value.screenshots.map((row) => ({
162
+ ...row,
163
+ file: row?.file ? create_type_file_from_wire(row.file) : false,
164
+ }))
165
+ : [],
166
+ };
167
+ }
168
+
169
+
170
+ /**
171
+ * @param {object} payload
172
+ * @param {Function|false} [callback]
173
+ *
174
+ * @returns {Promise<*>}
175
+ */
176
+ async details(payload, callback = false)
177
+ {
178
+ if (typeof callback?.before === 'function')
179
+ {
180
+ callback?.before({ payload });
181
+ }
182
+
183
+ return ApiService[ this.api_key ].details(payload).then((response) =>
184
+ {
185
+ if (typeof callback?.success === 'function')
186
+ {
187
+ callback?.success({ response, payload });
188
+ }
189
+ return response;
190
+ }).catch((error) =>
191
+ {
192
+ if (typeof callback?.error === 'function')
193
+ {
194
+ callback?.error({ error, payload });
195
+ }
196
+ throw error;
197
+ });
198
+ }
199
+ }