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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "complexqa_frontend_core",
3
- "version": "1.24.1",
3
+ "version": "1.26.1",
4
4
  "description": "core of web ",
5
5
  "type": "module",
6
6
  "exports": {
@@ -0,0 +1,55 @@
1
+ import { ApiAbstractElementClass } from './api_abstract_element_class.js';
2
+ import { typeAttachment } from '../types/family_elements/typeAttachment.js';
3
+
4
+ /**
5
+ * CRUD / Search / delete_file для attachment.
6
+ *
7
+ * @version v.0.1 (13/08/2026)
8
+ */
9
+ export class AttachmentApi extends ApiAbstractElementClass
10
+ {
11
+ module_prefix = 'attachment';
12
+
13
+ constructor(options)
14
+ {
15
+ super(options);
16
+ this.set_element_class_instance(typeAttachment);
17
+ }
18
+
19
+
20
+ /**
21
+ * Delete file in File App and unlink all attachments for that file_uuid.
22
+ *
23
+ * POST /web_api/attachment/delete_file
24
+ *
25
+ * @param {object} payload
26
+ * @param {string} payload.file_uuid
27
+ * @returns {Promise<{response: *, payload: *}>}
28
+ */
29
+ async delete_file(payload)
30
+ {
31
+ if (!this.module_prefix)
32
+ {
33
+ throw new Error('Error #attachment-delete-file-1152 in AttachmentApi');
34
+ }
35
+
36
+ if (this.stage === 'development')
37
+ {
38
+ return {
39
+ response: payload,
40
+ payload : payload,
41
+ };
42
+ }
43
+
44
+ let url = `/${ this.api_prefix }/${ this.module_prefix }/delete_file`;
45
+
46
+ payload = this.handle_request_payload(payload);
47
+ let response = this.api_request(url, payload);
48
+ response = this.handle_response(response);
49
+
50
+ return {
51
+ response: response,
52
+ payload : payload,
53
+ };
54
+ }
55
+ }
@@ -114,4 +114,26 @@ export class FileAppApi extends ApiAbstractClass
114
114
  payload : payload,
115
115
  };
116
116
  }
117
+
118
+
119
+ /**
120
+ * POST /web_api/file_app/delete_file
121
+ *
122
+ * @param {object} payload
123
+ * @param {string} payload.file_uuid
124
+ *
125
+ * @returns {Promise<{payload: object, response: object}>}
126
+ */
127
+ async delete_file(payload)
128
+ {
129
+ const url = `/${ this.api_prefix }/${ this.module_prefix }/delete_file`;
130
+ payload = this.handle_request_payload(payload);
131
+ let response = this.api_request(url, payload);
132
+ response = await this.handle_response(response, false);
133
+
134
+ return {
135
+ response: response,
136
+ payload : payload,
137
+ };
138
+ }
117
139
  }
@@ -13,6 +13,7 @@ import { TaskApi } from "./task_api.js";
13
13
  import { TestAccountApi } from "./test_account_api.js";
14
14
  import { BugApi } from "./bug_api.js";
15
15
  import { BugRelationApi } from "./bug_relation_api.js";
16
+ import { AttachmentApi } from "./attachment_api.js";
16
17
  import { TagApi } from "./tag_api.js";
17
18
  import { TagRelationApi } from "./tag_relation_api.js";
18
19
  import { TagColorApi } from "./tag/tag_color_api.js";
@@ -26,6 +27,8 @@ import { ContextOsApi } from "./context/context_os_api.js";
26
27
  import { ContextScreenResolutionApi } from "./context/context_screen_resolution_api.js";
27
28
  import { BrowserToolsUtilExecutionApi } from "./util/browser_tools_util_execution_api.js";
28
29
  import { BrowserToolsScreenshotMultiApi } from "./util/browser_tools_screenshot_multi_api.js";
30
+ import { TeamDomainApi } from "./team_domain_api.js";
31
+ import { UrlInspectApi } from "./util/url_inspect_api.js";
29
32
  import { TextDocumentApi } from "./text_document_api.js";
30
33
  import { PublicTextDocumentApi } from "./public_text_document_api.js";
31
34
  import { TextDocumentFolderApi } from "./text_document_folder_api.js";
@@ -170,12 +173,15 @@ export class Api
170
173
  this.test_account = new TestAccountApi(payload);
171
174
  this.bug = new BugApi(payload);
172
175
  this.bug_relation = new BugRelationApi(payload);
176
+ this.attachment = new AttachmentApi(payload);
173
177
  this.tag = new TagApi(payload);
174
178
  this.tag_relation = new TagRelationApi(payload);
175
179
  this.event = new EventApi(payload);
176
180
  this.execution_context = new ExecutionContextApi(payload);
177
181
  this.browser_tools_util_execution = new BrowserToolsUtilExecutionApi(payload);
178
182
  this.browser_tools_screenshot_multi = new BrowserToolsScreenshotMultiApi(payload);
183
+ this.team_domain = new TeamDomainApi(payload);
184
+ this.url_inspect = new UrlInspectApi(payload);
179
185
  this.file_app = new FileAppApi(payload);
180
186
  this.text_document = new TextDocumentApi(payload);
181
187
  this.text_document_folder = new TextDocumentFolderApi(payload);
@@ -0,0 +1,62 @@
1
+ import { ApiAbstractElementClass } from "./api_abstract_element_class.js";
2
+ import { typeTeamDomain } from "../types/family_elements/typeTeamDomain.js";
3
+
4
+
5
+ /**
6
+ * Team domain registry — search / create / verify / revoke.
7
+ *
8
+ * Base path: /web_api/team_domain
9
+ *
10
+ * @version v.0.1 (14/08/2026)
11
+ */
12
+ export class TeamDomainApi extends ApiAbstractElementClass
13
+ {
14
+ module_prefix = 'team_domain';
15
+
16
+
17
+ constructor(options)
18
+ {
19
+ super(options);
20
+ this.set_element_class_instance(typeTeamDomain);
21
+ }
22
+
23
+
24
+ /**
25
+ * @param {object} payload
26
+ *
27
+ * @returns {Promise<{payload, response: *}>}
28
+ */
29
+ async verify(payload)
30
+ {
31
+ let url = `/${ this.api_prefix }/${ this.module_prefix }/verify`;
32
+
33
+ payload = this.handle_request_payload(payload);
34
+ let response = this.api_request(url, payload);
35
+ response = this.handle_response(response, false);
36
+
37
+ return {
38
+ response: response,
39
+ payload : payload,
40
+ };
41
+ }
42
+
43
+
44
+ /**
45
+ * @param {object} payload
46
+ *
47
+ * @returns {Promise<{payload, response: *}>}
48
+ */
49
+ async revoke(payload)
50
+ {
51
+ let url = `/${ this.api_prefix }/${ this.module_prefix }/revoke`;
52
+
53
+ payload = this.handle_request_payload(payload);
54
+ let response = this.api_request(url, payload);
55
+ response = this.handle_response(response, false);
56
+
57
+ return {
58
+ response: response,
59
+ payload : payload,
60
+ };
61
+ }
62
+ }
@@ -49,7 +49,7 @@ export class TeamManagementApi extends ApiAbstractElementClass
49
49
 
50
50
  payload = this.handle_request_payload(payload);
51
51
  let response = this.api_request(url, payload);
52
- response = this.handle_response(response);
52
+ response = this.handle_response(response, false);
53
53
 
54
54
  return {
55
55
  response: response,
@@ -0,0 +1,54 @@
1
+ import { ApiAbstractElementClass } from "../api_abstract_element_class.js";
2
+ import { typeUtilExecutionUrlInspect } from "../../types/family_utils/typeUtilExecutionUrlInspect.js";
3
+
4
+
5
+ /**
6
+ * url.inspect suite — create / details / search.
7
+ *
8
+ * Base path: /web_api/util/url_inspect
9
+ *
10
+ * @version v.0.1 (14/08/2026)
11
+ */
12
+ export class UrlInspectApi extends ApiAbstractElementClass
13
+ {
14
+ module_prefix = 'util/url_inspect';
15
+
16
+
17
+ constructor(options)
18
+ {
19
+ super(options);
20
+ this.set_element_class_instance(typeUtilExecutionUrlInspect);
21
+ }
22
+
23
+
24
+ /**
25
+ * GET details/{util_execution_id}?project_id=
26
+ *
27
+ * @param {object} payload
28
+ *
29
+ * @returns {Promise<{payload, response: ReturnType<typeof typeUtilExecutionUrlInspect.composeDetails>|false}>}
30
+ */
31
+ async details(payload)
32
+ {
33
+ let util_execution_id = payload?.util_execution_id;
34
+
35
+ if (!util_execution_id)
36
+ {
37
+ throw new Error('util_execution_id is required for details');
38
+ }
39
+
40
+ let url = `/${ this.api_prefix }/${ this.module_prefix }/details/${ util_execution_id }`;
41
+
42
+ payload = this.handle_request_payload(payload);
43
+ const prev_method = this.method;
44
+ this.method = 'get';
45
+ let response = this.api_request(url, payload, 'GET');
46
+ this.method = prev_method;
47
+ response = await this.handle_response(response, false);
48
+
49
+ return {
50
+ response: typeUtilExecutionUrlInspect.composeDetails(response),
51
+ payload : payload,
52
+ };
53
+ }
54
+ }
@@ -4,15 +4,18 @@ import { typeTestRun } from '../../../types/family_elements/typeTestRun.js';
4
4
  import { typeBug } from '../../../types/family_elements/typeBug.js';
5
5
  import { typeBugRelation } from '../../../types/family_relation/typeBugRelation.js';
6
6
  import { typeTag } from '../../../types/family_elements/typeTag.js';
7
+ import { typeAttachment } from '../../../types/family_elements/typeAttachment.js';
7
8
  import { typeTagRelation } from '../../../types/family_relation/typeTagRelation.js';
8
9
  import { typeTestRunResult } from '../../../types/family_elements/typeTestRunResult.js';
9
10
  import { typeTestAccount } from '../../../types/family_elements/typeTestAccount.js';
10
11
  import { typeExecutionContext } from '../../../types/family_context/typeExecutionContext.js';
11
12
  import { typeTeamMember } from '../../../types/family_elements/typeTeamMember.js';
13
+ import { typeTeamDomain } from '../../../types/family_elements/typeTeamDomain.js';
12
14
  import { typeTestCaseStep } from '../../../types/family_elements/typeTestCaseStep.js';
13
15
  import { typeUser } from '../../../types/family_elements/typeUser.js';
14
16
  import { typeTeam } from '../../../types/family_elements/typeTeam.js';
15
17
  import { typeUtilExecutionScreenshotMulti } from '../../../types/family_utils/typeUtilExecutionScreenshotMulti.js';
18
+ import { typeUtilExecutionUrlInspect } from '../../../types/family_utils/typeUtilExecutionUrlInspect.js';
16
19
  import { typeTextDocument } from '../../../types/family_files/typeTextDocument.js';
17
20
  import { typeEvent } from '../../../types/family_events/typeEvent.js';
18
21
 
@@ -33,16 +36,19 @@ export const TABLE_ELEMENT_MODELS = {
33
36
  test_run : typeTestRun,
34
37
  bug : typeBug,
35
38
  bug_relation : typeBugRelation,
39
+ attachment : typeAttachment,
36
40
  tag : typeTag,
37
41
  tag_relation : typeTagRelation,
38
42
  test_run_result: typeTestRunResult,
39
43
  test_account : typeTestAccount,
40
44
  execution_context : typeExecutionContext,
41
45
  team_member : typeTeamMember,
46
+ team_domain : typeTeamDomain,
42
47
  test_case_step : typeTestCaseStep,
43
48
  user : typeUser,
44
49
  team : typeTeam,
45
50
  text_document : typeTextDocument,
46
51
  util_execution : typeUtilExecutionScreenshotMulti,
52
+ util_execution_url_inspect: typeUtilExecutionUrlInspect,
47
53
  event : typeEvent,
48
54
  };
@@ -0,0 +1,55 @@
1
+ import { typeTeamDomain } from '../../../types/family_elements/typeTeamDomain.js';
2
+ import { UserService } from '../../../services/UserService.js';
3
+ import {
4
+ createColumn,
5
+ createGoToColumn,
6
+ createPrimaryKeyColumn,
7
+ } from '../helpers/column_factory.js';
8
+ import { createListingFor, registerSection } from '../helpers/section_registry.js';
9
+
10
+ function build_team_domain_listing_columns(locale)
11
+ {
12
+ const model = new typeTeamDomain();
13
+
14
+ return [
15
+ createPrimaryKeyColumn(model, locale, { is_hide: true, default_sort: 'desc' }),
16
+ createColumn(model, locale, 'domain_canon', {
17
+ width : '280',
18
+ is_title : true,
19
+ is_filter : false,
20
+ is_editable: false,
21
+ }),
22
+ createColumn(model, locale, 'display_name', {
23
+ width : '200',
24
+ is_filter : false,
25
+ is_editable: false,
26
+ }),
27
+ createColumn(model, locale, 'verification_method', {
28
+ width : '180',
29
+ is_filter : false,
30
+ is_editable: false,
31
+ }),
32
+ createColumn(model, locale, 'domain_status', {
33
+ width : '160',
34
+ is_filter : false,
35
+ is_editable: false,
36
+ }),
37
+ createGoToColumn(model, locale),
38
+ ];
39
+ }
40
+
41
+
42
+ /**
43
+ * Секция `team_domain`: `listing`.
44
+ *
45
+ * @param {Object} config
46
+ * @returns {void}
47
+ */
48
+ export function bootstrap_team_domain(config)
49
+ {
50
+ const locale = UserService.get_current_language();
51
+
52
+ registerSection(config, 'team_domain', 'listing', build_team_domain_listing_columns(locale), {
53
+ for: createListingFor([]),
54
+ });
55
+ }
@@ -0,0 +1,60 @@
1
+ import { typeUtilExecutionUrlInspect } from '../../../types/family_utils/typeUtilExecutionUrlInspect.js';
2
+ import { UserService } from '../../../services/UserService.js';
3
+ import {
4
+ createColumn,
5
+ createGoToColumn,
6
+ createPrimaryKeyColumn,
7
+ } from '../helpers/column_factory.js';
8
+ import { createListingFor, registerSection } from '../helpers/section_registry.js';
9
+
10
+ function build_util_execution_url_inspect_listing_columns(locale)
11
+ {
12
+ const model = new typeUtilExecutionUrlInspect();
13
+
14
+ return [
15
+ createPrimaryKeyColumn(model, locale, { is_hide: true, default_sort: 'desc' }),
16
+ createColumn(model, locale, 'domain_canon', {
17
+ width : '240',
18
+ is_title : true,
19
+ is_filter : false,
20
+ is_editable: false,
21
+ }),
22
+ createColumn(model, locale, 'page_path', {
23
+ width : '280',
24
+ is_filter : false,
25
+ is_editable: false,
26
+ }),
27
+ createColumn(model, locale, 'suite_status', {
28
+ width : '160',
29
+ is_filter : false,
30
+ is_editable: false,
31
+ }),
32
+ createColumn(model, locale, 'project_id', {
33
+ width : '140',
34
+ is_filter : false,
35
+ is_editable: false,
36
+ }),
37
+ createColumn(model, locale, 'created_at', {
38
+ width : '180',
39
+ is_filter : false,
40
+ is_editable: false,
41
+ }),
42
+ createGoToColumn(model, locale),
43
+ ];
44
+ }
45
+
46
+
47
+ /**
48
+ * Секция `util_execution_url_inspect`: `listing`.
49
+ *
50
+ * @param {Object} config
51
+ * @returns {void}
52
+ */
53
+ export function bootstrap_util_execution_url_inspect(config)
54
+ {
55
+ const locale = UserService.get_current_language();
56
+
57
+ registerSection(config, 'util_execution_url_inspect', 'listing', build_util_execution_url_inspect_listing_columns(locale), {
58
+ for: createListingFor([ 'project_id' ]),
59
+ });
60
+ }
@@ -10,7 +10,9 @@ import { bootstrap_test_run_result } from './sections/test_run_result.js';
10
10
  import { bootstrap_test_account } from './sections/test_account.js';
11
11
  import { bootstrap_execution_context } from './sections/execution_context.js';
12
12
  import { bootstrap_util_execution } from './sections/util_execution.js';
13
+ import { bootstrap_util_execution_url_inspect } from './sections/util_execution_url_inspect.js';
13
14
  import { bootstrap_team_member } from './sections/team_member.js';
15
+ import { bootstrap_team_domain } from './sections/team_domain.js';
14
16
  import { bootstrap_event } from './sections/event.js';
15
17
  import { bootstrap_user } from './sections/user.js';
16
18
  import { bootstrap_team } from './sections/team.js';
@@ -122,7 +124,9 @@ export class TableConfiguration extends abstractAppConfiguration
122
124
  bootstrap_test_account(this.config);
123
125
  bootstrap_execution_context(this.config);
124
126
  bootstrap_util_execution(this.config);
127
+ bootstrap_util_execution_url_inspect(this.config);
125
128
  bootstrap_team_member(this.config);
129
+ bootstrap_team_domain(this.config);
126
130
  bootstrap_event(this.config);
127
131
  bootstrap_user(this.config);
128
132
  bootstrap_team(this.config);
package/publish/index.js CHANGED
@@ -17,6 +17,7 @@ export { typeTestRunResult } from './types/family_elements/typeTestRunResult.js'
17
17
  export { typeTestAccount } from './types/family_elements/typeTestAccount.js'
18
18
  export {typeBug} from './types/family_elements/typeBug.js';
19
19
  export { typeTag } from './types/family_elements/typeTag.js';
20
+ export { typeAttachment } from './types/family_elements/typeAttachment.js';
20
21
 
21
22
  export { familyRelation } from './types/core/1_familyRelation.js';
22
23
  export { typeBugRelation } from './types/family_relation/typeBugRelation.js';
@@ -37,6 +38,8 @@ export { typeUtilExecutionScreenshotMulti } from './types/family_utils/typeUtilE
37
38
  export { typeUtilExecutionScreenshotMultiCapture } from './types/family_utils/typeUtilExecutionScreenshotMultiCapture.js';
38
39
  export { typeUtilExecutionScreenshotMultiScreenshot } from './types/family_utils/typeUtilExecutionScreenshotMultiScreenshot.js';
39
40
  export { typeUtilExecutionScreenshotMultiCaptureError } from './types/family_utils/typeUtilExecutionScreenshotMultiCaptureError.js';
41
+ export { typeUtilExecutionUrlInspect } from './types/family_utils/typeUtilExecutionUrlInspect.js';
42
+ export { typeUtilExecutionUrlInspectCheck } from './types/family_utils/typeUtilExecutionUrlInspectCheck.js';
40
43
  export { typeUtilExecutionEvent } from './types/family_utils/typeUtilExecutionEvent.js';
41
44
 
42
45
  export { familyEvent } from './types/family_events/familyEvent.js';
@@ -65,6 +68,7 @@ export { text_document_editor_config, get_text_document_editor_config } from './
65
68
  export { typeUser } from './types/family_elements/typeUser.js';
66
69
  export { typeTeam } from './types/family_elements/typeTeam.js';
67
70
  export { typeTeamMember } from './types/family_elements/typeTeamMember.js';
71
+ export { typeTeamDomain } from './types/family_elements/typeTeamDomain.js';
68
72
  export { typeTeamTotalStatistic } from './types/family_contracts/typeTeamTotalStatistic.js';
69
73
 
70
74
  export { typeTask } from './types/family_elements/typeTask.js';
@@ -75,13 +75,53 @@ export class FileAppService extends abstractService
75
75
  }
76
76
 
77
77
 
78
+ /**
79
+ * Whether entity_type is present for File App binding.
80
+ * Empty / null / 0 → omit from token and upload init.
81
+ *
82
+ * @param {*} value
83
+ * @returns {boolean}
84
+ */
85
+ static #has_entity_type(value)
86
+ {
87
+ if (value === null || value === undefined)
88
+ {
89
+ return false;
90
+ }
91
+
92
+ const s = String(value).trim();
93
+
94
+ return s !== '' && s !== '0';
95
+ }
96
+
97
+
98
+ /**
99
+ * Whether entity_id is present for File App binding.
100
+ * Empty / null / 0 / NaN → omit from token and upload init.
101
+ *
102
+ * @param {*} value
103
+ * @returns {boolean}
104
+ */
105
+ static #has_entity_id(value)
106
+ {
107
+ if (value === null || value === undefined || value === '')
108
+ {
109
+ return false;
110
+ }
111
+
112
+ const n = Number(value);
113
+
114
+ return !Number.isNaN(n) && n !== 0;
115
+ }
116
+
117
+
78
118
  /**
79
119
  * Upload browser File/Blob to File App (token via Main App bridge).
80
120
  *
81
121
  * @param {object} payload
82
122
  * @param {File|Blob} payload.file
83
- * @param {string} payload.entity_type
84
- * @param {number} payload.entity_id
123
+ * @param {string} [payload.entity_type] — omit / null / 0 for unbound upload (attachments)
124
+ * @param {number} [payload.entity_id] — omit / null / 0 for unbound upload (attachments)
85
125
  * @param {string} payload.category
86
126
  * @param {string} [payload.original_name]
87
127
  * @param {string} [payload.file_uuid] — re-upload / new version for existing file
@@ -97,20 +137,24 @@ export class FileAppService extends abstractService
97
137
  throw new Error('FileAppService.upload_file: file is required');
98
138
  }
99
139
 
100
- const entity_type = String(payload.entity_type || '');
101
- const entity_id = Number(payload.entity_id);
102
- const category = String(payload.category || '');
103
- const mime_type = file.type || 'application/octet-stream';
104
- const size_bytes = Number(file.size || 0);
105
- const original_name = String(payload.original_name || file.name || 'upload');
106
- const api = FileAppService.#get_api_service();
107
-
108
- const token_wrap = await api.file_app.issue_access_token({
109
- scopes : [ 'file:upload', 'file:read' ],
110
- entity_type,
111
- entity_id,
140
+ const has_entity_type = FileAppService.#has_entity_type(payload.entity_type);
141
+ const has_entity_id = FileAppService.#has_entity_id(payload.entity_id);
142
+ const entity_type = has_entity_type ? String(payload.entity_type) : undefined;
143
+ const entity_id = has_entity_id ? Number(payload.entity_id) : undefined;
144
+ const category = String(payload.category || '');
145
+ const mime_type = file.type || 'application/octet-stream';
146
+ const size_bytes = Number(file.size || 0);
147
+ const original_name = String(payload.original_name || file.name || 'upload');
148
+ const api = FileAppService.#get_api_service();
149
+
150
+ const token_payload = {
151
+ scopes: [ 'file:upload', 'file:read' ],
112
152
  size_bytes,
113
- });
153
+ ...(has_entity_type ? { entity_type } : {}),
154
+ ...(has_entity_id ? { entity_id } : {}),
155
+ };
156
+
157
+ const token_wrap = await api.file_app.issue_access_token(token_payload);
114
158
 
115
159
  const token_data = await token_wrap?.response;
116
160
 
@@ -130,15 +174,17 @@ export class FileAppService extends abstractService
130
174
  throw new ApiException({ message: 'File App access token was not issued' });
131
175
  }
132
176
 
133
- const init_response = await axios.post(`${ file_app_url }/api/v1/uploads`, {
177
+ const init_payload = {
134
178
  category,
135
179
  mime_type,
136
180
  size_bytes,
137
181
  original_name,
138
- entity_type,
139
- entity_id,
182
+ ...(has_entity_type ? { entity_type } : {}),
183
+ ...(has_entity_id ? { entity_id } : {}),
140
184
  ...(payload.file_uuid ? { file_uuid: String(payload.file_uuid) } : {}),
141
- }, {
185
+ };
186
+
187
+ const init_response = await axios.post(`${ file_app_url }/api/v1/uploads`, init_payload, {
142
188
  headers: {
143
189
  Authorization: `Bearer ${ access_token }`,
144
190
  Accept : 'application/json',
@@ -183,8 +229,8 @@ export class FileAppService extends abstractService
183
229
  const wire = {
184
230
  ...confirmed,
185
231
  category : confirmed.category || category,
186
- entity_type: confirmed.entity_type || entity_type,
187
- entity_id : confirmed.entity_id ?? entity_id,
232
+ entity_type: confirmed.entity_type ?? entity_type ?? null,
233
+ entity_id : confirmed.entity_id ?? entity_id ?? null,
188
234
  mime_type : confirmed.mime_type || mime_type,
189
235
  };
190
236