@acorex-platform/extension-communication-meta-client 0.0.21

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.
@@ -0,0 +1,56 @@
1
+ import { extractRequestErrorInfo } from '@acorex-platform/framework-client/common';
2
+ import { RootConfig, AXP_COMMUNICATION_META_ERROR_CODES } from '@acorex-platform/extension-communication-meta-client/contracts';
3
+
4
+ const ROOT = `@${RootConfig.config.i18n}`;
5
+ const CommunicationMetaCommandI18n = {
6
+ errors: {
7
+ phoneNumberRequired: `${ROOT}:settings.whatsapp.errors.phone-number-required`,
8
+ accessTokenNotConfigured: `${ROOT}:settings.whatsapp.errors.access-token-not-configured`,
9
+ phoneNumberIdNotConfigured: `${ROOT}:settings.whatsapp.errors.phone-number-id-not-configured`,
10
+ tenantRequired: `${ROOT}:settings.whatsapp.errors.tenant-required`,
11
+ recipientNotFound: `${ROOT}:settings.whatsapp.errors.recipient-not-found`,
12
+ unauthorized: `${ROOT}:settings.whatsapp.errors.unauthorized`,
13
+ outsideWindow: `${ROOT}:settings.whatsapp.errors.outside-window`,
14
+ apiError: `${ROOT}:settings.whatsapp.errors.api-error`,
15
+ },
16
+ test: {
17
+ failed: `${ROOT}:settings.whatsapp.test.messages.failed`,
18
+ },
19
+ connect: {
20
+ failed: `${ROOT}:integration.connect.messages.failed`,
21
+ },
22
+ };
23
+
24
+ const ERROR_I18N_BY_CODE = {
25
+ [AXP_COMMUNICATION_META_ERROR_CODES.PHONE_NUMBER_REQUIRED]: CommunicationMetaCommandI18n.errors.phoneNumberRequired,
26
+ [AXP_COMMUNICATION_META_ERROR_CODES.ACCESS_TOKEN_NOT_CONFIGURED]: CommunicationMetaCommandI18n.errors.accessTokenNotConfigured,
27
+ [AXP_COMMUNICATION_META_ERROR_CODES.PHONE_NUMBER_ID_NOT_CONFIGURED]: CommunicationMetaCommandI18n.errors.phoneNumberIdNotConfigured,
28
+ [AXP_COMMUNICATION_META_ERROR_CODES.TENANT_REQUIRED]: CommunicationMetaCommandI18n.errors.tenantRequired,
29
+ [AXP_COMMUNICATION_META_ERROR_CODES.RECIPIENT_NOT_FOUND]: CommunicationMetaCommandI18n.errors.recipientNotFound,
30
+ [AXP_COMMUNICATION_META_ERROR_CODES.UNAUTHORIZED]: CommunicationMetaCommandI18n.errors.unauthorized,
31
+ [AXP_COMMUNICATION_META_ERROR_CODES.OUTSIDE_WINDOW]: CommunicationMetaCommandI18n.errors.outsideWindow,
32
+ [AXP_COMMUNICATION_META_ERROR_CODES.API_ERROR]: CommunicationMetaCommandI18n.errors.apiError,
33
+ };
34
+ async function resolveCommunicationMetaCommandError(translationService, error, fallbackKey = CommunicationMetaCommandI18n.test.failed) {
35
+ const httpInfo = extractRequestErrorInfo(error);
36
+ if (httpInfo?.code) {
37
+ const messageKey = ERROR_I18N_BY_CODE[httpInfo.code];
38
+ if (messageKey) {
39
+ const displayText = await translationService.translateAsync(messageKey, {
40
+ params: httpInfo.params,
41
+ });
42
+ return { messageKeyOrText: messageKey, displayText };
43
+ }
44
+ }
45
+ if (httpInfo?.message) {
46
+ return { messageKeyOrText: httpInfo.message, displayText: httpInfo.message };
47
+ }
48
+ if (error instanceof Error && error.message.trim()) {
49
+ return { messageKeyOrText: error.message, displayText: error.message };
50
+ }
51
+ const displayText = await translationService.translateAsync(fallbackKey);
52
+ return { messageKeyOrText: fallbackKey, displayText };
53
+ }
54
+
55
+ export { CommunicationMetaCommandI18n as C, resolveCommunicationMetaCommandError as r };
56
+ //# sourceMappingURL=acorex-platform-extension-communication-meta-client-communication-meta-command-error.util-Be3gOQPr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-extension-communication-meta-client-communication-meta-command-error.util-Be3gOQPr.mjs","sources":["../../../../libs/extensions/communication/meta/client/src/lib/commands/communication-meta-command.i18n.ts","../../../../libs/extensions/communication/meta/client/src/lib/commands/communication-meta-command-error.util.ts"],"sourcesContent":["import { RootConfig } from '@acorex-platform/extension-communication-meta-client/contracts';\n\nconst ROOT = `@${RootConfig.config.i18n}`;\n\nexport const CommunicationMetaCommandI18n = {\n errors: {\n phoneNumberRequired: `${ROOT}:settings.whatsapp.errors.phone-number-required`,\n accessTokenNotConfigured: `${ROOT}:settings.whatsapp.errors.access-token-not-configured`,\n phoneNumberIdNotConfigured: `${ROOT}:settings.whatsapp.errors.phone-number-id-not-configured`,\n tenantRequired: `${ROOT}:settings.whatsapp.errors.tenant-required`,\n recipientNotFound: `${ROOT}:settings.whatsapp.errors.recipient-not-found`,\n unauthorized: `${ROOT}:settings.whatsapp.errors.unauthorized`,\n outsideWindow: `${ROOT}:settings.whatsapp.errors.outside-window`,\n apiError: `${ROOT}:settings.whatsapp.errors.api-error`,\n },\n test: {\n failed: `${ROOT}:settings.whatsapp.test.messages.failed`,\n },\n connect: {\n failed: `${ROOT}:integration.connect.messages.failed`,\n },\n} as const;\n","import { extractRequestErrorInfo } from '@acorex-platform/framework-client/common';\nimport { AXP_COMMUNICATION_META_ERROR_CODES } from '@acorex-platform/extension-communication-meta-client/contracts';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { CommunicationMetaCommandI18n } from './communication-meta-command.i18n';\n\nconst ERROR_I18N_BY_CODE: Record<string, string> = {\n [AXP_COMMUNICATION_META_ERROR_CODES.PHONE_NUMBER_REQUIRED]: CommunicationMetaCommandI18n.errors.phoneNumberRequired,\n [AXP_COMMUNICATION_META_ERROR_CODES.ACCESS_TOKEN_NOT_CONFIGURED]:\n CommunicationMetaCommandI18n.errors.accessTokenNotConfigured,\n [AXP_COMMUNICATION_META_ERROR_CODES.PHONE_NUMBER_ID_NOT_CONFIGURED]:\n CommunicationMetaCommandI18n.errors.phoneNumberIdNotConfigured,\n [AXP_COMMUNICATION_META_ERROR_CODES.TENANT_REQUIRED]: CommunicationMetaCommandI18n.errors.tenantRequired,\n [AXP_COMMUNICATION_META_ERROR_CODES.RECIPIENT_NOT_FOUND]: CommunicationMetaCommandI18n.errors.recipientNotFound,\n [AXP_COMMUNICATION_META_ERROR_CODES.UNAUTHORIZED]: CommunicationMetaCommandI18n.errors.unauthorized,\n [AXP_COMMUNICATION_META_ERROR_CODES.OUTSIDE_WINDOW]: CommunicationMetaCommandI18n.errors.outsideWindow,\n [AXP_COMMUNICATION_META_ERROR_CODES.API_ERROR]: CommunicationMetaCommandI18n.errors.apiError,\n};\n\nexport async function resolveCommunicationMetaCommandError(\n translationService: AXTranslationService,\n error: unknown,\n fallbackKey: string = CommunicationMetaCommandI18n.test.failed,\n): Promise<{ messageKeyOrText: string; displayText: string }> {\n const httpInfo = extractRequestErrorInfo(error);\n if (httpInfo?.code) {\n const messageKey = ERROR_I18N_BY_CODE[httpInfo.code];\n if (messageKey) {\n const displayText = await translationService.translateAsync(messageKey, {\n params: httpInfo.params,\n });\n return { messageKeyOrText: messageKey, displayText };\n }\n }\n\n if (httpInfo?.message) {\n return { messageKeyOrText: httpInfo.message, displayText: httpInfo.message };\n }\n\n if (error instanceof Error && error.message.trim()) {\n return { messageKeyOrText: error.message, displayText: error.message };\n }\n\n const displayText = await translationService.translateAsync(fallbackKey);\n return { messageKeyOrText: fallbackKey, displayText };\n}\n"],"names":[],"mappings":";;;AAEA,MAAM,IAAI,GAAG,CAAA,CAAA,EAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAA,CAAE;AAElC,MAAM,4BAA4B,GAAG;AAC1C,IAAA,MAAM,EAAE;QACN,mBAAmB,EAAE,CAAA,EAAG,IAAI,CAAA,+CAAA,CAAiD;QAC7E,wBAAwB,EAAE,CAAA,EAAG,IAAI,CAAA,qDAAA,CAAuD;QACxF,0BAA0B,EAAE,CAAA,EAAG,IAAI,CAAA,wDAAA,CAA0D;QAC7F,cAAc,EAAE,CAAA,EAAG,IAAI,CAAA,yCAAA,CAA2C;QAClE,iBAAiB,EAAE,CAAA,EAAG,IAAI,CAAA,6CAAA,CAA+C;QACzE,YAAY,EAAE,CAAA,EAAG,IAAI,CAAA,sCAAA,CAAwC;QAC7D,aAAa,EAAE,CAAA,EAAG,IAAI,CAAA,wCAAA,CAA0C;QAChE,QAAQ,EAAE,CAAA,EAAG,IAAI,CAAA,mCAAA,CAAqC;AACvD,KAAA;AACD,IAAA,IAAI,EAAE;QACJ,MAAM,EAAE,CAAA,EAAG,IAAI,CAAA,uCAAA,CAAyC;AACzD,KAAA;AACD,IAAA,OAAO,EAAE;QACP,MAAM,EAAE,CAAA,EAAG,IAAI,CAAA,oCAAA,CAAsC;AACtD,KAAA;;;ACfH,MAAM,kBAAkB,GAA2B;IACjD,CAAC,kCAAkC,CAAC,qBAAqB,GAAG,4BAA4B,CAAC,MAAM,CAAC,mBAAmB;IACnH,CAAC,kCAAkC,CAAC,2BAA2B,GAC7D,4BAA4B,CAAC,MAAM,CAAC,wBAAwB;IAC9D,CAAC,kCAAkC,CAAC,8BAA8B,GAChE,4BAA4B,CAAC,MAAM,CAAC,0BAA0B;IAChE,CAAC,kCAAkC,CAAC,eAAe,GAAG,4BAA4B,CAAC,MAAM,CAAC,cAAc;IACxG,CAAC,kCAAkC,CAAC,mBAAmB,GAAG,4BAA4B,CAAC,MAAM,CAAC,iBAAiB;IAC/G,CAAC,kCAAkC,CAAC,YAAY,GAAG,4BAA4B,CAAC,MAAM,CAAC,YAAY;IACnG,CAAC,kCAAkC,CAAC,cAAc,GAAG,4BAA4B,CAAC,MAAM,CAAC,aAAa;IACtG,CAAC,kCAAkC,CAAC,SAAS,GAAG,4BAA4B,CAAC,MAAM,CAAC,QAAQ;CAC7F;AAEM,eAAe,oCAAoC,CACxD,kBAAwC,EACxC,KAAc,EACd,WAAA,GAAsB,4BAA4B,CAAC,IAAI,CAAC,MAAM,EAAA;AAE9D,IAAA,MAAM,QAAQ,GAAG,uBAAuB,CAAC,KAAK,CAAC;AAC/C,IAAA,IAAI,QAAQ,EAAE,IAAI,EAAE;QAClB,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpD,IAAI,UAAU,EAAE;YACd,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,UAAU,EAAE;gBACtE,MAAM,EAAE,QAAQ,CAAC,MAAM;AACxB,aAAA,CAAC;AACF,YAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE;QACtD;IACF;AAEA,IAAA,IAAI,QAAQ,EAAE,OAAO,EAAE;AACrB,QAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,OAAO,EAAE;IAC9E;IAEA,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE;AAClD,QAAA,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE;IACxE;IAEA,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,WAAW,CAAC;AACxE,IAAA,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE;AACvD;;;;"}
@@ -0,0 +1,137 @@
1
+ import { AXToastService } from '@acorex/components/toast';
2
+ import { AXTranslationService } from '@acorex/core/translation';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, Injectable } from '@angular/core';
5
+ import { r as resolveCommunicationMetaCommandError, C as CommunicationMetaCommandI18n } from './acorex-platform-extension-communication-meta-client-communication-meta-command-error.util-Be3gOQPr.mjs';
6
+ import { AXP_INTEGRATION_CONNECTION_STATUS } from '@acorex-platform/framework-shared/core';
7
+ import { AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
8
+ import { RootConfig } from '@acorex-platform/extension-communication-meta-client/contracts';
9
+ import { AXMIntegrationConnectionManager } from '@acorex-platform/module-integration-management-client';
10
+ import { AXPCommunicationMetaClient } from './acorex-platform-extension-communication-meta-client.mjs';
11
+
12
+ //#endregion
13
+ //#region ----- WhatsApp test dialog -----
14
+ class AXECommunicationWhatsAppTestDialogService {
15
+ constructor() {
16
+ this.layoutBuilder = inject(AXPLayoutBuilderService);
17
+ this.translationService = inject(AXTranslationService);
18
+ this.client = inject(AXPCommunicationMetaClient);
19
+ this.connectionManager = inject(AXMIntegrationConnectionManager);
20
+ }
21
+ async resolveDefaultPhoneNumber() {
22
+ const connection = await this.connectionManager.findByUniqueKey({
23
+ providerId: RootConfig.integration.providerId,
24
+ connectionScope: 'user',
25
+ connectionKey: 'default',
26
+ });
27
+ if (!connection ||
28
+ connection.status !== AXP_INTEGRATION_CONNECTION_STATUS.Connected ||
29
+ connection.isRevoked ||
30
+ connection.isDisabled) {
31
+ return '';
32
+ }
33
+ const config = (connection.config ?? {});
34
+ return String(config.phoneNumber ?? connection.externalAccountId ?? '').trim();
35
+ }
36
+ async openAndSendTestMessage() {
37
+ const defaultPhoneNumber = await this.resolveDefaultPhoneNumber();
38
+ try {
39
+ const result = await this.layoutBuilder
40
+ .create()
41
+ .dialog((dialog) => {
42
+ dialog
43
+ .setTitle('@extensions-communication-meta:settings.whatsapp.test.dialog.title')
44
+ .setSize('sm')
45
+ .setCloseButton(true)
46
+ .setContext({ phoneNumber: defaultPhoneNumber })
47
+ .content((flex) => {
48
+ flex
49
+ .setDirection('column')
50
+ .setGap('16px')
51
+ .formField('@extensions-communication-meta:settings.whatsapp.test.dialog.fields.phone-number.title', (field) => {
52
+ field.path('phoneNumber');
53
+ field.textBox({
54
+ validations: [{ rule: 'required' }],
55
+ placeholder: '@extensions-communication-meta:settings.whatsapp.test.dialog.fields.phone-number.placeholder',
56
+ });
57
+ });
58
+ })
59
+ .setActions((actions) => {
60
+ actions
61
+ .cancel('@general:actions.cancel.title')
62
+ .submit('@extensions-communication-meta:settings.whatsapp.test.dialog.actions.send');
63
+ })
64
+ .onAction(async (dialogRef) => {
65
+ if (dialogRef.action() === 'cancel') {
66
+ return null;
67
+ }
68
+ const context = dialogRef.context();
69
+ const phoneNumber = String(context?.['phoneNumber'] ?? '').trim();
70
+ if (!phoneNumber) {
71
+ throw new Error(await this.translationService.translateAsync('@extensions-communication-meta:settings.whatsapp.test.messages.phone-number-required'));
72
+ }
73
+ try {
74
+ const data = await this.client.testWhatsApp({ phoneNumber });
75
+ return { success: true, kind: 'object', data };
76
+ }
77
+ catch (error) {
78
+ const { messageKeyOrText } = await resolveCommunicationMetaCommandError(this.translationService, error);
79
+ return {
80
+ success: false,
81
+ message: { text: messageKeyOrText },
82
+ };
83
+ }
84
+ });
85
+ })
86
+ .show();
87
+ return resolveLayoutBuilderDialogResult(result);
88
+ }
89
+ catch (error) {
90
+ const { messageKeyOrText } = await resolveCommunicationMetaCommandError(this.translationService, error);
91
+ return {
92
+ success: false,
93
+ message: { text: messageKeyOrText },
94
+ };
95
+ }
96
+ }
97
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppTestDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
98
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppTestDialogService, providedIn: 'root' }); }
99
+ }
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppTestDialogService, decorators: [{
101
+ type: Injectable,
102
+ args: [{ providedIn: 'root' }]
103
+ }] });
104
+
105
+ //#region ----- WhatsApp test command -----
106
+ class CommunicationTestWhatsAppCommand {
107
+ constructor() {
108
+ this.dialog = inject(AXECommunicationWhatsAppTestDialogService);
109
+ this.toastService = inject(AXToastService);
110
+ this.translationService = inject(AXTranslationService);
111
+ }
112
+ async execute() {
113
+ const result = await this.dialog.openAndSendTestMessage();
114
+ // Cancel / header close — not a failure for the integrations panel.
115
+ if (!result) {
116
+ return { success: true, kind: 'object', data: null };
117
+ }
118
+ if (result.success) {
119
+ this.toastService.success(await this.translationService.translateAsync('@extensions-communication-meta:settings.whatsapp.test.messages.success'));
120
+ return result;
121
+ }
122
+ if (result.message?.text) {
123
+ const content = await this.translationService.translateAsync(result.message.text);
124
+ const title = await this.translationService.translateAsync(CommunicationMetaCommandI18n.test.failed);
125
+ this.toastService.show({ color: 'danger', title, content });
126
+ }
127
+ return result;
128
+ }
129
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CommunicationTestWhatsAppCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
130
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CommunicationTestWhatsAppCommand }); }
131
+ }
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: CommunicationTestWhatsAppCommand, decorators: [{
133
+ type: Injectable
134
+ }] });
135
+
136
+ export { CommunicationTestWhatsAppCommand };
137
+ //# sourceMappingURL=acorex-platform-extension-communication-meta-client-communication-test-whatsapp.command-GVjrHXJx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-extension-communication-meta-client-communication-test-whatsapp.command-GVjrHXJx.mjs","sources":["../../../../libs/extensions/communication/meta/client/src/lib/features/whatsapp/communication-whatsapp-test-dialog.service.ts","../../../../libs/extensions/communication/meta/client/src/lib/commands/communication-test-whatsapp.command.ts"],"sourcesContent":["import { AXTranslationService } from '@acorex/core/translation';\nimport { AXPRuntimeCommandResult, AXP_INTEGRATION_CONNECTION_STATUS } from '@acorex-platform/framework-shared/core';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { Injectable, inject } from '@angular/core';\nimport {\n RootConfig,\n type CommunicationMetaWhatsAppTestResult,\n type CommunicationMetaWhatsAppUserLinkConfig,\n} from '@acorex-platform/extension-communication-meta-client/contracts';\nimport { AXMIntegrationConnectionManager } from '@acorex-platform/module-integration-management-client';\nimport { resolveCommunicationMetaCommandError } from '../../commands/communication-meta-command-error.util';\nimport { AXPCommunicationMetaClient } from '../../communication-meta-client.port';\n\n//#region ----- Types -----\n\ntype WhatsAppTestDialogResult = AXPRuntimeCommandResult<CommunicationMetaWhatsAppTestResult> | null;\n\n//#endregion\n\n//#region ----- WhatsApp test dialog -----\n\n@Injectable({ providedIn: 'root' })\nexport class AXECommunicationWhatsAppTestDialogService {\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly translationService = inject(AXTranslationService);\n private readonly client = inject(AXPCommunicationMetaClient);\n private readonly connectionManager = inject(AXMIntegrationConnectionManager);\n\n private async resolveDefaultPhoneNumber(): Promise<string> {\n const connection = await this.connectionManager.findByUniqueKey({\n providerId: RootConfig.integration.providerId,\n connectionScope: 'user',\n connectionKey: 'default',\n });\n\n if (\n !connection ||\n connection.status !== AXP_INTEGRATION_CONNECTION_STATUS.Connected ||\n connection.isRevoked ||\n connection.isDisabled\n ) {\n return '';\n }\n\n const config = (connection.config ?? {}) as unknown as CommunicationMetaWhatsAppUserLinkConfig;\n return String(config.phoneNumber ?? connection.externalAccountId ?? '').trim();\n }\n\n async openAndSendTestMessage(): Promise<WhatsAppTestDialogResult> {\n const defaultPhoneNumber = await this.resolveDefaultPhoneNumber();\n\n try {\n const result = await this.layoutBuilder\n .create()\n .dialog<WhatsAppTestDialogResult>((dialog) => {\n dialog\n .setTitle('@extensions-communication-meta:settings.whatsapp.test.dialog.title')\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ phoneNumber: defaultPhoneNumber })\n .content((flex) => {\n flex\n .setDirection('column')\n .setGap('16px')\n .formField(\n '@extensions-communication-meta:settings.whatsapp.test.dialog.fields.phone-number.title',\n (field) => {\n field.path('phoneNumber');\n field.textBox({\n validations: [{ rule: 'required' }],\n placeholder:\n '@extensions-communication-meta:settings.whatsapp.test.dialog.fields.phone-number.placeholder',\n });\n },\n );\n })\n .setActions((actions) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit('@extensions-communication-meta:settings.whatsapp.test.dialog.actions.send');\n })\n .onAction(async (dialogRef: AXPDialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const context = dialogRef.context() as Record<string, unknown> | null;\n const phoneNumber = String(context?.['phoneNumber'] ?? '').trim();\n if (!phoneNumber) {\n throw new Error(\n await this.translationService.translateAsync(\n '@extensions-communication-meta:settings.whatsapp.test.messages.phone-number-required',\n ),\n );\n }\n\n try {\n const data = await this.client.testWhatsApp({ phoneNumber });\n return { success: true, kind: 'object', data };\n } catch (error) {\n const { messageKeyOrText } = await resolveCommunicationMetaCommandError(\n this.translationService,\n error,\n );\n return {\n success: false,\n message: { text: messageKeyOrText },\n };\n }\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<AXPRuntimeCommandResult<CommunicationMetaWhatsAppTestResult>>(result);\n } catch (error) {\n const { messageKeyOrText } = await resolveCommunicationMetaCommandError(this.translationService, error);\n return {\n success: false,\n message: { text: messageKeyOrText },\n };\n }\n }\n}\n\n//#endregion\n","import { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport type { AXPCommand, AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport type { AXPRuntimeCommandResult } from '@acorex-platform/framework-shared/core';\nimport type { CommunicationMetaWhatsAppTestResult } from '@acorex-platform/extension-communication-meta-client/contracts';\nimport { Injectable, inject } from '@angular/core';\nimport { CommunicationMetaCommandI18n } from './communication-meta-command.i18n';\nimport { AXECommunicationWhatsAppTestDialogService } from '../features/whatsapp/communication-whatsapp-test-dialog.service';\n\n//#region ----- WhatsApp test command -----\n\n@Injectable()\nexport class CommunicationTestWhatsAppCommand\n implements AXPCommand<void, CommunicationMetaWhatsAppTestResult | null>\n{\n private readonly dialog = inject(AXECommunicationWhatsAppTestDialogService);\n private readonly toastService = inject(AXToastService);\n private readonly translationService = inject(AXTranslationService);\n\n async execute(): AXPCommandExecuteResultPromise<CommunicationMetaWhatsAppTestResult | null> {\n const result = await this.dialog.openAndSendTestMessage();\n\n // Cancel / header close — not a failure for the integrations panel.\n if (!result) {\n return { success: true, kind: 'object', data: null };\n }\n\n if (result.success) {\n this.toastService.success(\n await this.translationService.translateAsync(\n '@extensions-communication-meta:settings.whatsapp.test.messages.success',\n ),\n );\n return result;\n }\n\n if (result.message?.text) {\n const content = await this.translationService.translateAsync(result.message.text);\n const title = await this.translationService.translateAsync(CommunicationMetaCommandI18n.test.failed);\n this.toastService.show({ color: 'danger', title, content });\n }\n\n return result;\n }\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,308 @@
1
+ import { AXToastService } from '@acorex/components/toast';
2
+ import { AXTranslationService } from '@acorex/core/translation';
3
+ import { AXP_INTEGRATION_CONNECTION_SCOPE, AXP_INTEGRATION_CONNECTION_STATUS, AXP_INTEGRATION_AUTH_METHOD_TYPE } from '@acorex-platform/framework-shared/core';
4
+ import { AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
5
+ import { AXMIntegrationConnectionManager, hasConfiguredIntegrationCredentials, AXP_INTEGRATION_CREDENTIAL_MASK, isMaskedIntegrationCredential, toSafeIntegrationConnectionDto } from '@acorex-platform/module-integration-management-client';
6
+ import * as i0 from '@angular/core';
7
+ import { inject, Injectable } from '@angular/core';
8
+ import { trim, defaultTo } from 'lodash-es';
9
+ import { RootConfig } from '@acorex-platform/extension-communication-meta-client/contracts';
10
+ import { r as resolveCommunicationMetaCommandError, C as CommunicationMetaCommandI18n } from './acorex-platform-extension-communication-meta-client-communication-meta-command-error.util-Be3gOQPr.mjs';
11
+
12
+ //#endregion
13
+ //#region ----- WhatsApp connect dialog -----
14
+ class AXECommunicationWhatsAppConnectDialogService {
15
+ constructor() {
16
+ //#region ----- Services & Dependencies -----
17
+ this.layoutBuilder = inject(AXPLayoutBuilderService);
18
+ this.translationService = inject(AXTranslationService);
19
+ }
20
+ //#endregion
21
+ async openAndLinkAccount() {
22
+ const result = await this.layoutBuilder
23
+ .create()
24
+ .dialog((dialog) => {
25
+ dialog
26
+ .setTitle('@extensions-communication-meta:integration.connect.dialog.title')
27
+ .setSize('sm')
28
+ .setCloseButton(true)
29
+ .setContext({ phoneNumber: '', displayName: '' })
30
+ .content((flex) => {
31
+ flex
32
+ .setDirection('column')
33
+ .setGap('12px')
34
+ .customWidget('text-block-layout', {
35
+ content: '@extensions-communication-meta:integration.connect.dialog.instructions',
36
+ })
37
+ .formField('@extensions-communication-meta:integration.connect.dialog.fields.phone-number.title', (field) => {
38
+ field.path('phoneNumber');
39
+ field.textBox({
40
+ validations: [{ rule: 'required' }],
41
+ placeholder: '@extensions-communication-meta:integration.connect.dialog.fields.phone-number.placeholder',
42
+ });
43
+ })
44
+ .formField('@extensions-communication-meta:integration.connect.dialog.fields.display-name.title', (field) => {
45
+ field.path('displayName');
46
+ field.textBox({
47
+ placeholder: '@extensions-communication-meta:integration.connect.dialog.fields.display-name.placeholder',
48
+ });
49
+ });
50
+ })
51
+ .setActions((actions) => {
52
+ actions
53
+ .cancel('@general:actions.cancel.title')
54
+ .submit('@extensions-communication-meta:integration.connect.dialog.actions.connect');
55
+ })
56
+ .onAction(async (ref) => {
57
+ if (ref.action() === 'cancel') {
58
+ return null;
59
+ }
60
+ const context = ref.context();
61
+ const phoneNumber = String(context?.phoneNumber ?? '').trim();
62
+ if (!phoneNumber) {
63
+ throw new Error(await this.translationService.translateAsync('@extensions-communication-meta:settings.whatsapp.errors.phone-number-required'));
64
+ }
65
+ const displayName = String(context?.displayName ?? '').trim();
66
+ return {
67
+ phoneNumber,
68
+ ...(displayName ? { displayName } : {}),
69
+ };
70
+ });
71
+ })
72
+ .show();
73
+ return resolveLayoutBuilderDialogResult(result);
74
+ }
75
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppConnectDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
76
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppConnectDialogService, providedIn: 'root' }); }
77
+ }
78
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXECommunicationWhatsAppConnectDialogService, decorators: [{
79
+ type: Injectable,
80
+ args: [{ providedIn: 'root' }]
81
+ }] });
82
+
83
+ //#region ---- Connect WhatsApp (tenant Cloud API or user link) ----
84
+ class ConnectWhatsAppCommand {
85
+ constructor() {
86
+ this.connectionManager = inject(AXMIntegrationConnectionManager);
87
+ this.connectDialog = inject(AXECommunicationWhatsAppConnectDialogService);
88
+ this.layoutBuilder = inject(AXPLayoutBuilderService);
89
+ this.toastService = inject(AXToastService);
90
+ this.translationService = inject(AXTranslationService);
91
+ }
92
+ async execute(input = {}) {
93
+ const connectionScope = input.connectionScope ?? AXP_INTEGRATION_CONNECTION_SCOPE.User;
94
+ if (connectionScope === AXP_INTEGRATION_CONNECTION_SCOPE.Tenant) {
95
+ return this.connectTenantCloudApi(input);
96
+ }
97
+ return this.connectUserLink(input);
98
+ }
99
+ async connectTenantCloudApi(input) {
100
+ try {
101
+ const providerId = input.providerId ?? RootConfig.integration.providerId;
102
+ const connectionScope = AXP_INTEGRATION_CONNECTION_SCOPE.Tenant;
103
+ const I18N = `@${RootConfig.config.i18n}:integration.connect.tenant`;
104
+ const existing = await this.connectionManager.findByUniqueKey({
105
+ providerId,
106
+ connectionScope,
107
+ connectionKey: 'default',
108
+ });
109
+ const isReconfigure = hasConfiguredIntegrationCredentials(existing);
110
+ const existingConfig = (existing?.config ?? {});
111
+ const form = await this.openTenantConnectDialog({
112
+ i18nPrefix: I18N,
113
+ isReconfigure,
114
+ context: {
115
+ accessToken: isReconfigure ? AXP_INTEGRATION_CREDENTIAL_MASK : '',
116
+ phoneNumberId: existingConfig.phoneNumberId ?? '',
117
+ webhookVerifyToken: isReconfigure && existingConfig.webhookVerifyToken
118
+ ? AXP_INTEGRATION_CREDENTIAL_MASK
119
+ : '',
120
+ appSecret: isReconfigure && existingConfig.appSecret ? AXP_INTEGRATION_CREDENTIAL_MASK : '',
121
+ },
122
+ });
123
+ if (!form) {
124
+ return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
125
+ }
126
+ let accessToken = trim(form.accessToken);
127
+ if (isMaskedIntegrationCredential(accessToken) && existing) {
128
+ accessToken = trim(existingConfig.accessToken ?? '');
129
+ }
130
+ let webhookVerifyToken = trim(form.webhookVerifyToken);
131
+ if (isMaskedIntegrationCredential(webhookVerifyToken) && existing) {
132
+ webhookVerifyToken = trim(existingConfig.webhookVerifyToken ?? '');
133
+ }
134
+ let appSecret = trim(form.appSecret);
135
+ if (isMaskedIntegrationCredential(appSecret) && existing) {
136
+ appSecret = trim(existingConfig.appSecret ?? '');
137
+ }
138
+ const phoneNumberId = trim(form.phoneNumberId);
139
+ if (!accessToken || !phoneNumberId) {
140
+ return {
141
+ success: false,
142
+ message: {
143
+ text: await this.translationService.translateAsync(`${I18N}.messages.credentials-required`),
144
+ },
145
+ };
146
+ }
147
+ const connection = await this.connectionManager.upsertConnection({
148
+ providerId,
149
+ authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.ApiToken,
150
+ connectionScope,
151
+ connectionKey: 'default',
152
+ displayName: existing?.displayName ?? 'WhatsApp',
153
+ externalAccountId: phoneNumberId,
154
+ externalAccountName: AXP_INTEGRATION_CREDENTIAL_MASK,
155
+ config: {
156
+ accessToken,
157
+ phoneNumberId,
158
+ webhookVerifyToken: webhookVerifyToken || null,
159
+ appSecret: appSecret || null,
160
+ },
161
+ status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,
162
+ isRevoked: false,
163
+ isDisabled: false,
164
+ });
165
+ this.toastService.success(await this.translationService.translateAsync(`${I18N}.messages.success`));
166
+ return { success: true, kind: 'object',
167
+ data: {
168
+ outcome: 'connected',
169
+ connection: toSafeIntegrationConnectionDto(connection),
170
+ },
171
+ };
172
+ }
173
+ catch (error) {
174
+ const { displayText } = await resolveCommunicationMetaCommandError(this.translationService, error, CommunicationMetaCommandI18n.connect.failed);
175
+ return { success: false, message: { text: displayText } };
176
+ }
177
+ }
178
+ async connectUserLink(input) {
179
+ try {
180
+ const providerId = input.providerId ?? RootConfig.integration.providerId;
181
+ const connectionScope = AXP_INTEGRATION_CONNECTION_SCOPE.User;
182
+ const existing = await this.connectionManager.findByUniqueKey({
183
+ providerId,
184
+ connectionScope,
185
+ connectionKey: 'default',
186
+ });
187
+ const linked = await this.connectDialog.openAndLinkAccount();
188
+ if (!linked || typeof linked !== 'object' || !('phoneNumber' in linked)) {
189
+ return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
190
+ }
191
+ const phoneNumber = trim(linked.phoneNumber);
192
+ if (!phoneNumber) {
193
+ return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
194
+ }
195
+ const displayName = defaultTo(trim(linked.displayName), 'WhatsApp');
196
+ const connection = await this.connectionManager.upsertConnection({
197
+ providerId,
198
+ authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.ApiToken,
199
+ connectionScope,
200
+ connectionKey: 'default',
201
+ displayName: existing?.displayName ?? displayName,
202
+ externalAccountId: phoneNumber,
203
+ externalAccountName: displayName,
204
+ config: {
205
+ phoneNumber,
206
+ displayName: displayName || null,
207
+ },
208
+ status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,
209
+ isRevoked: false,
210
+ isDisabled: false,
211
+ });
212
+ this.toastService.success(await this.translationService.translateAsync('@extensions-communication-meta:integration.connect.messages.success'));
213
+ return { success: true, kind: 'object',
214
+ data: {
215
+ outcome: 'connected',
216
+ connection: toSafeIntegrationConnectionDto(connection),
217
+ },
218
+ };
219
+ }
220
+ catch (error) {
221
+ const { displayText } = await resolveCommunicationMetaCommandError(this.translationService, error, CommunicationMetaCommandI18n.connect.failed);
222
+ return { success: false, message: { text: displayText } };
223
+ }
224
+ }
225
+ async openTenantConnectDialog(input) {
226
+ const result = await this.layoutBuilder
227
+ .create()
228
+ .dialog((dialog) => {
229
+ dialog
230
+ .setTitle(input.isReconfigure
231
+ ? `${input.i18nPrefix}.dialog.configure-title`
232
+ : `${input.i18nPrefix}.dialog.title`)
233
+ .setSize('md')
234
+ .setCloseButton(true)
235
+ .setContext({ ...input.context })
236
+ .content((flex) => {
237
+ flex
238
+ .setDirection('column')
239
+ .setGap('12px')
240
+ .customWidget('text-block-layout', {
241
+ content: `${input.i18nPrefix}.dialog.instructions`,
242
+ })
243
+ .formField(`${input.i18nPrefix}.dialog.fields.access-token`, (field) => {
244
+ field.path('accessToken');
245
+ field.passwordBox({
246
+ placeholder: `${input.i18nPrefix}.dialog.placeholders.access-token`,
247
+ revealToggle: true,
248
+ validations: [{ rule: 'required' }],
249
+ });
250
+ })
251
+ .formField(`${input.i18nPrefix}.dialog.fields.phone-number-id`, (field) => {
252
+ field.path('phoneNumberId');
253
+ field.textBox({
254
+ placeholder: `${input.i18nPrefix}.dialog.placeholders.phone-number-id`,
255
+ validations: [{ rule: 'required' }],
256
+ });
257
+ })
258
+ .formField(`${input.i18nPrefix}.dialog.fields.webhook-verify-token`, (field) => {
259
+ field.path('webhookVerifyToken');
260
+ field.passwordBox({
261
+ placeholder: `${input.i18nPrefix}.dialog.placeholders.webhook-verify-token`,
262
+ revealToggle: true,
263
+ });
264
+ })
265
+ .formField(`${input.i18nPrefix}.dialog.fields.app-secret`, (field) => {
266
+ field.path('appSecret');
267
+ field.passwordBox({
268
+ placeholder: `${input.i18nPrefix}.dialog.placeholders.app-secret`,
269
+ revealToggle: true,
270
+ });
271
+ });
272
+ })
273
+ .setActions((actions) => {
274
+ actions
275
+ .cancel('@general:actions.cancel.title')
276
+ .submit(`${input.i18nPrefix}.dialog.actions.save`);
277
+ })
278
+ .onAction(async (ref) => {
279
+ if (ref.action() === 'cancel') {
280
+ return null;
281
+ }
282
+ const ctx = ref.context();
283
+ const accessToken = trim(ctx.accessToken);
284
+ const phoneNumberId = trim(ctx.phoneNumberId);
285
+ if (!accessToken || !phoneNumberId) {
286
+ throw new Error(`${input.i18nPrefix}.messages.credentials-required`);
287
+ }
288
+ return {
289
+ accessToken,
290
+ phoneNumberId,
291
+ webhookVerifyToken: trim(ctx.webhookVerifyToken),
292
+ appSecret: trim(ctx.appSecret),
293
+ };
294
+ });
295
+ })
296
+ .show();
297
+ return resolveLayoutBuilderDialogResult(result);
298
+ }
299
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectWhatsAppCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
300
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectWhatsAppCommand, providedIn: 'root' }); }
301
+ }
302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectWhatsAppCommand, decorators: [{
303
+ type: Injectable,
304
+ args: [{ providedIn: 'root' }]
305
+ }] });
306
+
307
+ export { ConnectWhatsAppCommand };
308
+ //# sourceMappingURL=acorex-platform-extension-communication-meta-client-connect-whatsapp.command-Dpo-31ex.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-extension-communication-meta-client-connect-whatsapp.command-Dpo-31ex.mjs","sources":["../../../../libs/extensions/communication/meta/client/src/lib/features/connect/communication-whatsapp-connect-dialog.service.ts","../../../../libs/extensions/communication/meta/client/src/lib/features/connect/connect-whatsapp.command.ts"],"sourcesContent":["import { AXTranslationService } from '@acorex/core/translation';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n type IActionBuilder,\n type IDialogBuilder,\n type IFlexContainerBuilder,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { Injectable, inject } from '@angular/core';\n\n//#region ----- Types -----\n\nexport interface CommunicationWhatsAppConnectResult {\n phoneNumber: string;\n displayName?: string;\n}\n\ninterface WhatsAppConnectDialogContext {\n phoneNumber: string;\n displayName: string;\n}\n\n//#endregion\n\n//#region ----- WhatsApp connect dialog -----\n\n@Injectable({ providedIn: 'root' })\nexport class AXECommunicationWhatsAppConnectDialogService {\n //#region ----- Services & Dependencies -----\n\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly translationService = inject(AXTranslationService);\n\n //#endregion\n\n async openAndLinkAccount(): Promise<CommunicationWhatsAppConnectResult | null> {\n const result = await this.layoutBuilder\n .create()\n .dialog<CommunicationWhatsAppConnectResult | null>((dialog: IDialogBuilder<CommunicationWhatsAppConnectResult | null>) => {\n dialog\n .setTitle('@extensions-communication-meta:integration.connect.dialog.title')\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ phoneNumber: '', displayName: '' } satisfies WhatsAppConnectDialogContext)\n .content((flex: IFlexContainerBuilder) => {\n flex\n .setDirection('column')\n .setGap('12px')\n .customWidget('text-block-layout', {\n content: '@extensions-communication-meta:integration.connect.dialog.instructions',\n })\n .formField('@extensions-communication-meta:integration.connect.dialog.fields.phone-number.title', (field) => {\n field.path('phoneNumber');\n field.textBox({\n validations: [{ rule: 'required' }],\n placeholder:\n '@extensions-communication-meta:integration.connect.dialog.fields.phone-number.placeholder',\n });\n })\n .formField('@extensions-communication-meta:integration.connect.dialog.fields.display-name.title', (field) => {\n field.path('displayName');\n field.textBox({\n placeholder:\n '@extensions-communication-meta:integration.connect.dialog.fields.display-name.placeholder',\n });\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit('@extensions-communication-meta:integration.connect.dialog.actions.connect');\n })\n .onAction(async (ref: AXPDialogRef) => {\n if (ref.action() === 'cancel') {\n return null;\n }\n\n const context = ref.context() as WhatsAppConnectDialogContext;\n const phoneNumber = String(context?.phoneNumber ?? '').trim();\n if (!phoneNumber) {\n throw new Error(\n await this.translationService.translateAsync(\n '@extensions-communication-meta:settings.whatsapp.errors.phone-number-required',\n ),\n );\n }\n\n const displayName = String(context?.displayName ?? '').trim();\n return {\n phoneNumber,\n ...(displayName ? { displayName } : {}),\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<CommunicationWhatsAppConnectResult>(result);\n }\n}\n\n//#endregion\n\n//#endregion\n","import { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n AXP_INTEGRATION_CONNECTION_SCOPE,\n AXP_INTEGRATION_CONNECTION_STATUS,\n type AXPRuntimeCommandResult,\n type AXPIntegrationConnectionScope,\n} from '@acorex-platform/framework-shared/core';\nimport type { AXPCommand, AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n type IActionBuilder,\n type IDialogBuilder,\n type IFlexContainerBuilder,\n} from '@acorex-platform/framework-client/layout/builder';\nimport {\n AXMIntegrationConnectionManager,\n AXP_INTEGRATION_CREDENTIAL_MASK,\n hasConfiguredIntegrationCredentials,\n isMaskedIntegrationCredential,\n toSafeIntegrationConnectionDto,\n type ConnectCommandResult,\n} from '@acorex-platform/module-integration-management-client';\nimport { Injectable, inject } from '@angular/core';\nimport { defaultTo, trim } from 'lodash-es';\nimport {\n RootConfig,\n type CommunicationMetaWhatsAppTenantConnectionConfig,\n} from '@acorex-platform/extension-communication-meta-client/contracts';\nimport { resolveCommunicationMetaCommandError } from '../../commands/communication-meta-command-error.util';\nimport { CommunicationMetaCommandI18n } from '../../commands/communication-meta-command.i18n';\nimport { AXECommunicationWhatsAppConnectDialogService } from './communication-whatsapp-connect-dialog.service';\n\nexport interface ConnectWhatsAppCommandInput {\n providerId?: string;\n connectionScope?: AXPIntegrationConnectionScope;\n}\n\ninterface WhatsAppTenantConnectFormContext {\n accessToken: string;\n phoneNumberId: string;\n webhookVerifyToken: string;\n appSecret: string;\n}\n\ninterface WhatsAppTenantConnectFormResult {\n accessToken: string;\n phoneNumberId: string;\n webhookVerifyToken: string;\n appSecret: string;\n}\n\n//#region ---- Connect WhatsApp (tenant Cloud API or user link) ----\n\n@Injectable({ providedIn: 'root' })\nexport class ConnectWhatsAppCommand implements AXPCommand<ConnectWhatsAppCommandInput, ConnectCommandResult> {\n private readonly connectionManager = inject(AXMIntegrationConnectionManager);\n private readonly connectDialog = inject(AXECommunicationWhatsAppConnectDialogService);\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly toastService = inject(AXToastService);\n private readonly translationService = inject(AXTranslationService);\n\n async execute(input: ConnectWhatsAppCommandInput = {}): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n const connectionScope = input.connectionScope ?? AXP_INTEGRATION_CONNECTION_SCOPE.User;\n if (connectionScope === AXP_INTEGRATION_CONNECTION_SCOPE.Tenant) {\n return this.connectTenantCloudApi(input);\n }\n return this.connectUserLink(input);\n }\n\n private async connectTenantCloudApi(\n input: ConnectWhatsAppCommandInput,\n ): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n try {\n const providerId = input.providerId ?? RootConfig.integration.providerId;\n const connectionScope = AXP_INTEGRATION_CONNECTION_SCOPE.Tenant;\n const I18N = `@${RootConfig.config.i18n}:integration.connect.tenant`;\n const existing = await this.connectionManager.findByUniqueKey({\n providerId,\n connectionScope,\n connectionKey: 'default',\n });\n const isReconfigure = hasConfiguredIntegrationCredentials(existing);\n const existingConfig = (existing?.config ?? {}) as CommunicationMetaWhatsAppTenantConnectionConfig;\n\n const form = await this.openTenantConnectDialog({\n i18nPrefix: I18N,\n isReconfigure,\n context: {\n accessToken: isReconfigure ? AXP_INTEGRATION_CREDENTIAL_MASK : '',\n phoneNumberId: existingConfig.phoneNumberId ?? '',\n webhookVerifyToken: isReconfigure && existingConfig.webhookVerifyToken\n ? AXP_INTEGRATION_CREDENTIAL_MASK\n : '',\n appSecret: isReconfigure && existingConfig.appSecret ? AXP_INTEGRATION_CREDENTIAL_MASK : '',\n },\n });\n\n if (!form) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n let accessToken = trim(form.accessToken);\n if (isMaskedIntegrationCredential(accessToken) && existing) {\n accessToken = trim(existingConfig.accessToken ?? '');\n }\n\n let webhookVerifyToken = trim(form.webhookVerifyToken);\n if (isMaskedIntegrationCredential(webhookVerifyToken) && existing) {\n webhookVerifyToken = trim(existingConfig.webhookVerifyToken ?? '');\n }\n\n let appSecret = trim(form.appSecret);\n if (isMaskedIntegrationCredential(appSecret) && existing) {\n appSecret = trim(existingConfig.appSecret ?? '');\n }\n\n const phoneNumberId = trim(form.phoneNumberId);\n if (!accessToken || !phoneNumberId) {\n return {\n success: false,\n message: {\n text: await this.translationService.translateAsync(`${I18N}.messages.credentials-required`),\n },\n };\n }\n\n const connection = await this.connectionManager.upsertConnection({\n providerId,\n authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.ApiToken,\n connectionScope,\n connectionKey: 'default',\n displayName: existing?.displayName ?? 'WhatsApp',\n externalAccountId: phoneNumberId,\n externalAccountName: AXP_INTEGRATION_CREDENTIAL_MASK,\n config: {\n accessToken,\n phoneNumberId,\n webhookVerifyToken: webhookVerifyToken || null,\n appSecret: appSecret || null,\n },\n status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n isRevoked: false,\n isDisabled: false,\n });\n\n this.toastService.success(\n await this.translationService.translateAsync(`${I18N}.messages.success`),\n );\n\n return { success: true, kind: 'object',\n data: {\n outcome: 'connected',\n connection: toSafeIntegrationConnectionDto(connection),\n },\n };\n } catch (error: unknown) {\n const { displayText } = await resolveCommunicationMetaCommandError(\n this.translationService,\n error,\n CommunicationMetaCommandI18n.connect.failed,\n );\n return { success: false, message: { text: displayText } };\n }\n }\n\n private async connectUserLink(\n input: ConnectWhatsAppCommandInput,\n ): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n try {\n const providerId = input.providerId ?? RootConfig.integration.providerId;\n const connectionScope = AXP_INTEGRATION_CONNECTION_SCOPE.User;\n const existing = await this.connectionManager.findByUniqueKey({\n providerId,\n connectionScope,\n connectionKey: 'default',\n });\n\n const linked = await this.connectDialog.openAndLinkAccount();\n if (!linked || typeof linked !== 'object' || !('phoneNumber' in linked)) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n const phoneNumber = trim(linked.phoneNumber);\n if (!phoneNumber) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n const displayName = defaultTo(trim(linked.displayName), 'WhatsApp');\n\n const connection = await this.connectionManager.upsertConnection({\n providerId,\n authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.ApiToken,\n connectionScope,\n connectionKey: 'default',\n displayName: existing?.displayName ?? displayName,\n externalAccountId: phoneNumber,\n externalAccountName: displayName,\n config: {\n phoneNumber,\n displayName: displayName || null,\n },\n status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n isRevoked: false,\n isDisabled: false,\n });\n\n this.toastService.success(\n await this.translationService.translateAsync(\n '@extensions-communication-meta:integration.connect.messages.success',\n ),\n );\n\n return { success: true, kind: 'object',\n data: {\n outcome: 'connected',\n connection: toSafeIntegrationConnectionDto(connection),\n },\n };\n } catch (error: unknown) {\n const { displayText } = await resolveCommunicationMetaCommandError(\n this.translationService,\n error,\n CommunicationMetaCommandI18n.connect.failed,\n );\n return { success: false, message: { text: displayText } };\n }\n }\n\n private async openTenantConnectDialog(input: {\n i18nPrefix: string;\n isReconfigure: boolean;\n context: WhatsAppTenantConnectFormContext;\n }): Promise<WhatsAppTenantConnectFormResult | null> {\n const result = await this.layoutBuilder\n .create()\n .dialog<WhatsAppTenantConnectFormResult | null>((dialog: IDialogBuilder<WhatsAppTenantConnectFormResult | null>) => {\n dialog\n .setTitle(\n input.isReconfigure\n ? `${input.i18nPrefix}.dialog.configure-title`\n : `${input.i18nPrefix}.dialog.title`,\n )\n .setSize('md')\n .setCloseButton(true)\n .setContext({ ...input.context })\n .content((flex: IFlexContainerBuilder) => {\n flex\n .setDirection('column')\n .setGap('12px')\n .customWidget('text-block-layout', {\n content: `${input.i18nPrefix}.dialog.instructions`,\n })\n .formField(`${input.i18nPrefix}.dialog.fields.access-token`, (field) => {\n field.path('accessToken');\n field.passwordBox({\n placeholder: `${input.i18nPrefix}.dialog.placeholders.access-token`,\n revealToggle: true,\n validations: [{ rule: 'required' }],\n });\n })\n .formField(`${input.i18nPrefix}.dialog.fields.phone-number-id`, (field) => {\n field.path('phoneNumberId');\n field.textBox({\n placeholder: `${input.i18nPrefix}.dialog.placeholders.phone-number-id`,\n validations: [{ rule: 'required' }],\n });\n })\n .formField(`${input.i18nPrefix}.dialog.fields.webhook-verify-token`, (field) => {\n field.path('webhookVerifyToken');\n field.passwordBox({\n placeholder: `${input.i18nPrefix}.dialog.placeholders.webhook-verify-token`,\n revealToggle: true,\n });\n })\n .formField(`${input.i18nPrefix}.dialog.fields.app-secret`, (field) => {\n field.path('appSecret');\n field.passwordBox({\n placeholder: `${input.i18nPrefix}.dialog.placeholders.app-secret`,\n revealToggle: true,\n });\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit(`${input.i18nPrefix}.dialog.actions.save`);\n })\n .onAction(async (ref: AXPDialogRef) => {\n if (ref.action() === 'cancel') {\n return null;\n }\n const ctx = ref.context() as WhatsAppTenantConnectFormContext;\n const accessToken = trim(ctx.accessToken);\n const phoneNumberId = trim(ctx.phoneNumberId);\n if (!accessToken || !phoneNumberId) {\n throw new Error(`${input.i18nPrefix}.messages.credentials-required`);\n }\n return {\n accessToken,\n phoneNumberId,\n webhookVerifyToken: trim(ctx.webhookVerifyToken),\n appSecret: trim(ctx.appSecret),\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<WhatsAppTenantConnectFormResult>(result);\n }\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}