@acorex-platform/extension-project-management-servicem8-client 0.0.30 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-CkDOwDrg.mjs → acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs} +3 -3
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs.map +1 -0
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client-contracts.mjs +9 -4
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client-contracts.mjs.map +1 -1
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client.mjs +191 -36
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client.mjs.map +1 -1
- package/package.json +2 -2
- package/types/acorex-platform-extension-project-management-servicem8-client-contracts.d.ts +75 -4
- package/fesm2022/acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-CkDOwDrg.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AXP_INTEGRATION_CONNECTION_STATUS, AXP_INTEGRATION_AUTH_METHOD_TYPE } from '@acorex-platform/framework-shared/core';
|
|
1
|
+
import { createRandomUuid, AXP_INTEGRATION_CONNECTION_STATUS, AXP_INTEGRATION_AUTH_METHOD_TYPE } from '@acorex-platform/framework-shared/core';
|
|
2
2
|
import { AXPSessionService } from '@acorex-platform/framework-client/auth';
|
|
3
3
|
import { AXMIntegrationConnectionManager, AXP_INTEGRATION_CREDENTIAL_MASK, toSafeIntegrationConnectionDto, isMaskedIntegrationCredential, hasConfiguredIntegrationCredentials } from '@acorex-platform/module-integration-management-client';
|
|
4
4
|
import { AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
|
|
@@ -33,7 +33,7 @@ class ConnectServiceM8Command {
|
|
|
33
33
|
const isReconfigure = !!existing;
|
|
34
34
|
const existingConfig = (existing?.config ?? {});
|
|
35
35
|
const connectionKey = existing?.connectionKey
|
|
36
|
-
?? (trim(input.connectionKey) ||
|
|
36
|
+
?? (trim(input.connectionKey) || createRandomUuid());
|
|
37
37
|
const title = await this.translationService.translateAsync(isReconfigure
|
|
38
38
|
? '@extensions-servicem8:integration.connect.dialog.reconfigure-title'
|
|
39
39
|
: '@extensions-servicem8:integration.connect.dialog.title');
|
|
@@ -225,4 +225,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
225
225
|
}] });
|
|
226
226
|
|
|
227
227
|
export { ConnectServiceM8Command };
|
|
228
|
-
//# sourceMappingURL=acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-
|
|
228
|
+
//# sourceMappingURL=acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs","sources":["../../../../libs/extensions/project-management/servicem8/client/src/lib/features/connect/servicem8-oauth.util.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/connect/connect-servicem8.command.ts"],"sourcesContent":["//#region ---- ServiceM8 OAuth helpers (client) ----\n\n/** Resolves the demo app path segment used in the OAuth callback URL. */\nexport function resolveServiceM8OAuthAppName(applicationName: string | null | undefined): string {\n const trimmed = String(applicationName ?? '').trim();\n return trimmed || 'demo';\n}\n\n//#endregion\n","//#region ---- Connect ServiceM8 (OAuth authorization code) ----\n\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n AXP_INTEGRATION_CONNECTION_STATUS,\n type AXPRuntimeCommandResult,\n type AXPIntegrationConnectionScope,\n createRandomUuid,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\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 {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n type IActionBuilder,\n type IDialogBuilder,\n type IFlexContainerBuilder,\n type IFormFieldBuilder,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXEServiceM8OAuthHttpClient } from '../../api/servicem8-oauth-http.client';\nimport { Injectable, inject } from '@angular/core';\nimport { defaultTo, isEmpty, trim } from 'lodash-es';\nimport {\n AXE_SERVICEM8_API_BASE_URL,\n AXE_SERVICEM8_OAUTH_SCOPES,\n type AXEServiceM8ConnectionConfig,\n} from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport type { AXMIntegrationManagementIntegrationConnectionEntityModel } from '@acorex-platform/module-integration-management-client/contracts';\nimport { resolveServiceM8OAuthAppName } from './servicem8-oauth.util';\n\nexport interface ConnectServiceM8CommandInput {\n providerId?: string;\n connectionScope?: AXPIntegrationConnectionScope;\n /** When set, reconfigure / reconnect this existing connection. */\n connectionId?: string;\n /** Optional explicit key; new connections get a generated key when omitted. */\n connectionKey?: string;\n}\n\ninterface AXEServiceM8ConnectFormContext {\n displayName: string;\n clientId: string;\n clientSecret: string;\n}\n\ninterface AXEServiceM8ConnectFormResult {\n displayName: string;\n clientId: string;\n clientSecret: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ConnectServiceM8Command implements AXPCommand<ConnectServiceM8CommandInput, ConnectCommandResult> {\n private readonly connectionManager = inject(AXMIntegrationConnectionManager);\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly translationService = inject(AXTranslationService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly servicem8Http = inject(AXEServiceM8OAuthHttpClient);\n\n async execute(input: ConnectServiceM8CommandInput = {}): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n try {\n const providerId = input.providerId ?? 'servicem8';\n const connectionScope = input.connectionScope ?? 'tenant';\n const existing = await this.resolveExistingConnection(providerId, connectionScope, input);\n const isReconfigure = !!existing;\n const existingConfig = (existing?.config ?? {}) as AXEServiceM8ConnectionConfig;\n const connectionKey =\n existing?.connectionKey\n ?? (trim(input.connectionKey) || createRandomUuid());\n\n const title = await this.translationService.translateAsync(\n isReconfigure\n ? '@extensions-servicem8:integration.connect.dialog.reconfigure-title'\n : '@extensions-servicem8:integration.connect.dialog.title',\n );\n\n const form = await this.openConnectDialog({\n title: title ?? 'Connect ServiceM8',\n context: {\n displayName: existing?.displayName ?? 'ServiceM8',\n clientId: existingConfig.clientId ?? '',\n clientSecret: isReconfigure ? AXP_INTEGRATION_CREDENTIAL_MASK : '',\n },\n existing,\n existingConfig,\n isReconfigure,\n });\n\n if (!form) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n const credentialsChanged = this.credentialsChanged(existingConfig, form);\n const needsAuthorization = this.needsOAuthAuthorization(existingConfig, credentialsChanged);\n\n const config: AXEServiceM8ConnectionConfig = {\n clientId: form.clientId,\n clientSecret: form.clientSecret,\n scope: AXE_SERVICEM8_OAUTH_SCOPES,\n ...(credentialsChanged\n ? {}\n : {\n accessToken: existingConfig.accessToken,\n refreshToken: existingConfig.refreshToken,\n tokenExpiresAt: existingConfig.tokenExpiresAt,\n oauthTokenJson: existingConfig.oauthTokenJson,\n }),\n };\n\n const connection = await this.connectionManager.upsertConnection({\n providerId,\n authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.OAuth2,\n connectionScope,\n connectionKey,\n displayName: defaultTo(trim(form.displayName), 'ServiceM8'),\n instanceUrl: AXE_SERVICEM8_API_BASE_URL,\n externalAccountName: AXP_INTEGRATION_CREDENTIAL_MASK,\n config: config as Record<string, unknown>,\n status: needsAuthorization\n ? AXP_INTEGRATION_CONNECTION_STATUS.PendingAuthorization\n : AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n isRevoked: false,\n isDisabled: false,\n });\n\n if (needsAuthorization) {\n const appName = resolveServiceM8OAuthAppName(this.sessionService.application?.name);\n const redirectUri = `${window.location.origin}/${appName}/integrations/oauth/callback/${providerId}`;\n const oauth = await this.servicem8Http.startOAuth({\n redirectUri,\n connectionId: connection.id,\n });\n return { success: true, kind: 'object',\n data: { outcome: 'redirect', redirectUrl: oauth.redirectUrl },\n };\n }\n\n const validation = await this.servicem8Http.validateOAuth({ connectionId: connection.id });\n if (!validation.valid) {\n return {\n success: false,\n message: { text: validation.message ?? 'ServiceM8 connection validation failed. Re-authorize ServiceM8.' },\n };\n }\n\n const refreshed = await this.connectionManager.getByIdForCurrentUser(connection.id);\n return { success: true, kind: 'object',\n data: {\n outcome: 'connected',\n connection: toSafeIntegrationConnectionDto(refreshed ?? connection),\n },\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to connect ServiceM8.';\n return { success: false, message: { text: message } };\n }\n }\n\n private async resolveExistingConnection(\n providerId: string,\n connectionScope: AXPIntegrationConnectionScope,\n input: ConnectServiceM8CommandInput,\n ): Promise<AXMIntegrationManagementIntegrationConnectionEntityModel | null> {\n if (input.connectionId) {\n const byId = await this.connectionManager.getByIdForCurrentUser(input.connectionId);\n if (!byId) {\n throw new Error('Connection not found or access denied.');\n }\n return byId;\n }\n\n const connectionKey = trim(input.connectionKey);\n if (!connectionKey) {\n return null;\n }\n\n return this.connectionManager.findByUniqueKey({\n providerId,\n connectionScope,\n connectionKey,\n });\n }\n\n private credentialsChanged(\n existingConfig: AXEServiceM8ConnectionConfig,\n form: AXEServiceM8ConnectFormResult,\n ): boolean {\n if (trim(form.clientId) !== trim(existingConfig.clientId ?? '')) {\n return true;\n }\n if (!isMaskedIntegrationCredential(form.clientSecret)) {\n return true;\n }\n return false;\n }\n\n private needsOAuthAuthorization(\n existingConfig: AXEServiceM8ConnectionConfig,\n credentialsChanged: boolean,\n ): boolean {\n if (credentialsChanged) {\n return true;\n }\n return isEmpty(trim(existingConfig.refreshToken ?? ''));\n }\n\n private async openConnectDialog(input: {\n title: string;\n context: AXEServiceM8ConnectFormContext;\n existing: AXMIntegrationManagementIntegrationConnectionEntityModel | null;\n existingConfig: AXEServiceM8ConnectionConfig;\n isReconfigure: boolean;\n }): Promise<AXEServiceM8ConnectFormResult | null> {\n const result: unknown = await this.layoutBuilder\n .create()\n .dialog<AXEServiceM8ConnectFormResult | null>((dialog: IDialogBuilder<AXEServiceM8ConnectFormResult | null>) => {\n dialog\n .setTitle(input.title)\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: '@extensions-servicem8:integration.connect.instructions',\n })\n .formField('@extensions-servicem8:integration.connect.fields.display-name', (field: IFormFieldBuilder) => {\n field.path('displayName');\n field.textBox({\n placeholder: '@extensions-servicem8:integration.connect.placeholders.display-name',\n });\n })\n .formField('@extensions-servicem8:integration.auth.oauth.client-id.label', (field) => {\n field.path('clientId');\n field.textBox({\n placeholder: '@extensions-servicem8:integration.auth.oauth.client-id.placeholder',\n validations: [{ rule: 'required' }],\n });\n })\n .formField('@extensions-servicem8:integration.auth.oauth.client-secret.label', (field) => {\n field.path('clientSecret');\n field.passwordBox({\n placeholder: '@extensions-servicem8:integration.auth.oauth.client-secret.placeholder',\n revealToggle: true,\n validations: input.isReconfigure ? [] : [{ rule: 'required' }],\n });\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit(\n input.isReconfigure && hasConfiguredIntegrationCredentials(input.existing)\n ? '@extensions-servicem8:integration.connect.actions.save'\n : '@extensions-servicem8:integration.connect.actions.save-and-authorize',\n );\n })\n .onAction(async (ref: AXPDialogRef) => {\n if (ref.action() === 'cancel') {\n return null;\n }\n\n const ctx = ref.context() as AXEServiceM8ConnectFormContext;\n const clientId = trim(ctx.clientId);\n if (!clientId) {\n throw new Error('ServiceM8 App ID is required.');\n }\n\n let clientSecret = trim(ctx.clientSecret);\n if (isMaskedIntegrationCredential(clientSecret) && input.existing) {\n clientSecret = trim(input.existingConfig.clientSecret ?? '');\n }\n if (!clientSecret) {\n throw new Error('ServiceM8 App Secret is required.');\n }\n\n return {\n displayName: trim(ctx.displayName) || 'ServiceM8',\n clientId,\n clientSecret,\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<AXEServiceM8ConnectFormResult>(result);\n }\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
|
package/fesm2022/acorex-platform-extension-project-management-servicem8-client-contracts.mjs
CHANGED
|
@@ -19,10 +19,12 @@ const RootConfig = {
|
|
|
19
19
|
const AXEServiceM8CommandKeys = {
|
|
20
20
|
ConnectionConnect: 'servicem8-extension.Connection:Connect',
|
|
21
21
|
ConnectionCompleteOAuth: 'servicem8-extension.Connection:CompleteOAuth',
|
|
22
|
+
ConnectionLifecycle: 'servicem8-extension.Connection:Lifecycle',
|
|
22
23
|
OAuthStart: 'servicem8-extension.OAuth:Start',
|
|
23
24
|
OAuthComplete: 'servicem8-extension.OAuth:Complete',
|
|
24
25
|
OAuthValidate: 'servicem8-extension.OAuth:Validate',
|
|
25
26
|
ProjectImportFromServiceM8: 'servicem8-extension.Project:ImportFromServiceM8',
|
|
27
|
+
CustomerImportFromServiceM8: 'servicem8-extension.Customer:ImportFromServiceM8',
|
|
26
28
|
ProjectSync: 'servicem8-extension.Project:Sync',
|
|
27
29
|
JobsPull: 'servicem8-extension.Jobs:Pull',
|
|
28
30
|
JobsRefresh: 'servicem8-extension.Jobs:Refresh',
|
|
@@ -74,6 +76,9 @@ const AXEServiceM8Permissions = {
|
|
|
74
76
|
ProjectImport: {
|
|
75
77
|
Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,
|
|
76
78
|
},
|
|
79
|
+
CustomerImport: {
|
|
80
|
+
Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,
|
|
81
|
+
},
|
|
77
82
|
ProjectSync: {
|
|
78
83
|
Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,
|
|
79
84
|
},
|
|
@@ -87,7 +92,7 @@ const AXEServiceM8Permissions = {
|
|
|
87
92
|
//#region ---- ServiceM8 OAuth API (client ↔ server) ----
|
|
88
93
|
//#endregion
|
|
89
94
|
|
|
90
|
-
//#region ---- Remote ServiceM8
|
|
95
|
+
//#region ---- Remote ServiceM8 DTOs ----
|
|
91
96
|
//#endregion
|
|
92
97
|
|
|
93
98
|
//#region ---- ServiceM8 API / OAuth constants ----
|
|
@@ -98,10 +103,10 @@ const AXE_SERVICEM8_OAUTH_TOKEN_URL = 'https://go.servicem8.com/oauth/access_tok
|
|
|
98
103
|
/** REST API base URL stored on connection `instanceUrl`. */
|
|
99
104
|
const AXE_SERVICEM8_API_BASE_URL = 'https://api.servicem8.com';
|
|
100
105
|
/**
|
|
101
|
-
* OAuth scopes for connect.
|
|
102
|
-
*
|
|
106
|
+
* OAuth scopes for connect / authorize.
|
|
107
|
+
* Space-separated; encoded as `scope=` query value by the OAuth start flow.
|
|
103
108
|
*/
|
|
104
|
-
const AXE_SERVICEM8_OAUTH_SCOPES = 'read_jobs
|
|
109
|
+
const AXE_SERVICEM8_OAUTH_SCOPES = 'read_customers read_jobs read_staff read_job_contacts read_job_attachments publish_job_attachments read_customer_contacts';
|
|
105
110
|
//#endregion
|
|
106
111
|
|
|
107
112
|
/**
|
package/fesm2022/acorex-platform-extension-project-management-servicem8-client-contracts.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client-contracts.mjs","sources":["../../../../libs/extensions/project-management/servicem8/contracts/src/root-config.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/commands.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/menu.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/permission.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/connection.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/oauth.api.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/project-sync.api.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/servicem8.constants.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/acorex-platform-extension-project-management-servicem8-client-contracts.ts"],"sourcesContent":["//#region ---- Module Config ----\n\nconst config = {\n i18n: 'extensions-servicem8',\n};\n\nconst MODULE_NAME = 'ServiceM8Extension';\n\nexport const RootConfig = {\n config,\n module: {\n name: MODULE_NAME,\n title: `@${config.i18n}:integration.display-name`,\n icon: 'fa-light fa-briefcase',\n },\n};\n\n//#endregion\n","//#region ---- Command Keys ----\n\nexport const AXEServiceM8CommandKeys = {\n ConnectionConnect: 'servicem8-extension.Connection:Connect',\n ConnectionCompleteOAuth: 'servicem8-extension.Connection:CompleteOAuth',\n OAuthStart: 'servicem8-extension.OAuth:Start',\n OAuthComplete: 'servicem8-extension.OAuth:Complete',\n OAuthValidate: 'servicem8-extension.OAuth:Validate',\n ProjectImportFromServiceM8: 'servicem8-extension.Project:ImportFromServiceM8',\n ProjectSync: 'servicem8-extension.Project:Sync',\n JobsPull: 'servicem8-extension.Jobs:Pull',\n JobsRefresh: 'servicem8-extension.Jobs:Refresh',\n} as const;\n\n//#endregion\n","//#region ---- Menu Keys ----\n\nexport const AXEServiceM8MenuKeys = {\n ServiceM8ExtensionConfig: 'servicem8-extension:Menu:Configuration',\n} as const;\n\n//#endregion\n","//#region ---- Permission Keys ----\n\n/**\n * Administration capabilities used by this extension.\n * Domain capability keys for this module. Root groups live in `AXPCommonPermissionGroupKeys` (common contracts).\n */\nexport const AXPAdministrationPermissionKeys = {\n Access: 'Administration:Permission:Access',\n MaintainUsersAndRoles: 'Administration:Permission:MaintainUsersAndRoles',\n ManageSessions: 'Administration:Permission:ManageSessions',\n MaintainPolicies: 'Administration:Permission:MaintainPolicies',\n ViewIntegrations: 'Administration:Permission:ViewIntegrations',\n MaintainConnections: 'Administration:Permission:MaintainConnections',\n ManageIntegrationActions: 'Administration:Permission:ManageIntegrationActions',\n MaintainWorkflows: 'Administration:Permission:MaintainWorkflows',\n ManageWorkflowActions: 'Administration:Permission:ManageWorkflowActions',\n ViewRules: 'Administration:Permission:ViewRules',\n MaintainRules: 'Administration:Permission:MaintainRules',\n ManageRuleActions: 'Administration:Permission:ManageRuleActions',\n MaintainAi: 'Administration:Permission:MaintainAi',\n UseAiAssist: 'Administration:Permission:UseAiAssist',\n MaintainDashboards: 'Administration:Permission:MaintainDashboards',\n ViewJobs: 'Administration:Permission:ViewJobs',\n ManageJobActions: 'Administration:Permission:ManageJobActions',\n ViewObservability: 'Administration:Permission:ViewObservability',\n MaintainObservability: 'Administration:Permission:MaintainObservability',\n} as const;\n\n/**\n * @deprecated Prefer {@link AXPAdministrationPermissionKeys}.\n * Legacy nested shape kept so existing imports compile during migration.\n */\nexport const AXEServiceM8Permissions = {\n ServiceM8Extension: {\n Management: AXPAdministrationPermissionKeys.MaintainConnections,\n Catalog: {\n View: AXPAdministrationPermissionKeys.ViewIntegrations,\n },\n ProjectImport: {\n Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,\n },\n ProjectSync: {\n Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,\n },\n },\n} as const;\n\n//#endregion\n","//#region ---- ServiceM8 tenant connection config ----\n\n/** Stored on IntegrationManagement connection `config` for tenant-scoped ServiceM8. */\nexport interface AXEServiceM8ConnectionConfig {\n /** OAuth2 App ID from the ServiceM8 developer add-on. */\n clientId?: string;\n /** OAuth2 App Secret from the ServiceM8 developer add-on. */\n clientSecret?: string;\n /** Space-separated scopes granted at authorize time. */\n scope?: string;\n /** Current bearer token (authorization-code flow). */\n accessToken?: string;\n /** Refresh token from ServiceM8 token response. */\n refreshToken?: string;\n /** ISO timestamp when `accessToken` expires. */\n tokenExpiresAt?: string;\n /** Full ServiceM8 token JSON response. */\n oauthTokenJson?: string;\n /** Background job pull sync state (server-managed). */\n jobsSync?: AXEServiceM8JobsSyncState;\n}\n\n/** ServiceM8 job pull sync state stored on the tenant connection `config.jobsSync`. */\nexport interface AXEServiceM8JobsSyncState {\n /** ISO timestamp — last successful job pull (incremental sync watermark). */\n lastSyncAt?: string;\n /** ISO timestamp — last full snapshot reconcile (deactivation pass). */\n lastFullReconcileAt?: string;\n}\n\n//#endregion\n","//#region ---- ServiceM8 OAuth API (client ↔ server) ----\n\nexport interface AXEServiceM8OAuthStartRequest {\n redirectUri: string;\n connectionId?: string;\n}\n\nexport interface AXEServiceM8OAuthStartResponse {\n redirectUrl: string;\n state: string;\n}\n\nexport interface AXEServiceM8OAuthCompleteRequest {\n state: string;\n code: string;\n}\n\nexport interface AXEServiceM8OAuthCompleteResponse {\n connectionId: string;\n}\n\nexport interface AXEServiceM8OAuthValidateRequest {\n connectionId?: string;\n}\n\nexport interface AXEServiceM8OAuthValidateResponse {\n valid: boolean;\n message?: string;\n}\n\n//#endregion\n","//#region ---- Remote ServiceM8 job DTO ----\n\nimport type { AXEServiceM8ProjectSyncStrategy } from './sync.types';\n\n/** Subset of ServiceM8 `job.json` fields used for cache / import / sync. */\nexport interface AXEServiceM8RemoteJob {\n uuid: string;\n generated_job_id?: string | null;\n job_description?: string | null;\n job_address?: string | null;\n status?: string | null;\n date?: string | null;\n edit_date?: string | null;\n company_uuid?: string | null;\n company_name?: string | null;\n purchase_order_number?: string | null;\n active?: number | boolean | null;\n billing_address?: string | null;\n work_done_description?: string | null;\n}\n\n//#endregion\n\n//#region ---- API request / response ----\n\nexport interface AXEServiceM8PullJobsRequest {\n /** Maximum ServiceM8 jobs to pull into the cache (default 250, max 1000). */\n maxJobs?: number;\n /**\n * When true, runs a full snapshot (no incremental filter) and reconciles deactivations.\n * When false (default for schedules), pulls jobs modified since the last successful sync.\n */\n force?: boolean;\n}\n\nexport interface AXEServiceM8PullJobsResponse {\n upserted: number;\n deactivated: number;\n /** True when incremental pull found no modified jobs in ServiceM8. */\n skipped?: boolean;\n /** Whether this run used incremental or full snapshot mode. */\n syncMode?: 'incremental' | 'full';\n}\n\nexport interface AXEServiceM8ImportJobRequest {\n remoteRecordId: string;\n projectTypeId: string;\n syncStrategy: AXEServiceM8ProjectSyncStrategy;\n}\n\nexport interface AXEServiceM8ImportJobResponse {\n platformProjectId: string;\n created: boolean;\n}\n\nexport interface AXEServiceM8SyncPlatformProjectRequest {\n platformProjectId: string;\n}\n\n//#endregion\n","//#region ---- ServiceM8 API / OAuth constants ----\n\n/** Public OAuth authorize endpoint (fixed host). */\nexport const AXE_SERVICEM8_OAUTH_AUTHORIZE_URL = 'https://go.servicem8.com/oauth/authorize';\n\n/** Public OAuth token endpoint (authorization_code + refresh_token). */\nexport const AXE_SERVICEM8_OAUTH_TOKEN_URL = 'https://go.servicem8.com/oauth/access_token';\n\n/** REST API base URL stored on connection `instanceUrl`. */\nexport const AXE_SERVICEM8_API_BASE_URL = 'https://api.servicem8.com';\n\n/**\n * OAuth scopes for connect.\n * `manage_jobs` is included so push sync can be added later without re-consent.\n */\nexport const AXE_SERVICEM8_OAUTH_SCOPES = 'read_jobs manage_jobs vendor';\n\n//#endregion\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;AAEA,MAAM,MAAM,GAAG;AACb,IAAA,IAAI,EAAE,sBAAsB;CAC7B;AAED,MAAM,WAAW,GAAG,oBAAoB;AAEjC,MAAM,UAAU,GAAG;IACxB,MAAM;AACN,IAAA,MAAM,EAAE;AACN,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,KAAK,EAAE,CAAA,CAAA,EAAI,MAAM,CAAC,IAAI,CAAA,yBAAA,CAA2B;AACjD,QAAA,IAAI,EAAE,uBAAuB;AAC9B,KAAA;;AAGH;;ACjBA;AAEO,MAAM,uBAAuB,GAAG;AACrC,IAAA,iBAAiB,EAAE,wCAAwC;AAC3D,IAAA,uBAAuB,EAAE,8CAA8C;AACvE,IAAA,UAAU,EAAE,iCAAiC;AAC7C,IAAA,aAAa,EAAE,oCAAoC;AACnD,IAAA,aAAa,EAAE,oCAAoC;AACnD,IAAA,0BAA0B,EAAE,iDAAiD;AAC7E,IAAA,WAAW,EAAE,kCAAkC;AAC/C,IAAA,QAAQ,EAAE,+BAA+B;AACzC,IAAA,WAAW,EAAE,kCAAkC;;AAGjD;;ACdA;AAEO,MAAM,oBAAoB,GAAG;AAClC,IAAA,wBAAwB,EAAE,wCAAwC;;AAGpE;;ACNA;AAEA;;;AAGG;AACI,MAAM,+BAA+B,GAAG;AAC7C,IAAA,MAAM,EAAE,kCAAkC;AAC1C,IAAA,qBAAqB,EAAE,iDAAiD;AACxE,IAAA,cAAc,EAAE,0CAA0C;AAC1D,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,mBAAmB,EAAE,+CAA+C;AACpE,IAAA,wBAAwB,EAAE,oDAAoD;AAC9E,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,qBAAqB,EAAE,iDAAiD;AACxE,IAAA,SAAS,EAAE,qCAAqC;AAChD,IAAA,aAAa,EAAE,yCAAyC;AACxD,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,UAAU,EAAE,sCAAsC;AAClD,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,kBAAkB,EAAE,8CAA8C;AAClE,IAAA,QAAQ,EAAE,oCAAoC;AAC9C,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,qBAAqB,EAAE,iDAAiD;;AAG1E;;;AAGG;AACI,MAAM,uBAAuB,GAAG;AACrC,IAAA,kBAAkB,EAAE;QAClB,UAAU,EAAE,+BAA+B,CAAC,mBAAmB;AAC/D,QAAA,OAAO,EAAE;YACP,IAAI,EAAE,+BAA+B,CAAC,gBAAgB;AACvD,SAAA;AACD,QAAA,aAAa,EAAE;YACb,OAAO,EAAE,+BAA+B,CAAC,wBAAwB;AAClE,SAAA;AACD,QAAA,WAAW,EAAE;YACX,OAAO,EAAE,+BAA+B,CAAC,wBAAwB;AAClE,SAAA;AACF,KAAA;;AAGH;;AC/CA;AA8BA;;AC9BA;AA8BA;;AC9BA;AA2DA;;AC3DA;AAEA;AACO,MAAM,iCAAiC,GAAG;AAEjD;AACO,MAAM,6BAA6B,GAAG;AAE7C;AACO,MAAM,0BAA0B,GAAG;AAE1C;;;AAGG;AACI,MAAM,0BAA0B,GAAG;AAE1C;;ACjBA;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client-contracts.mjs","sources":["../../../../libs/extensions/project-management/servicem8/contracts/src/root-config.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/commands.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/menu.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/permission.keys.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/connection.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/oauth.api.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/project-sync.api.types.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/servicem8.constants.ts","../../../../libs/extensions/project-management/servicem8/contracts/src/acorex-platform-extension-project-management-servicem8-client-contracts.ts"],"sourcesContent":["//#region ---- Module Config ----\n\nconst config = {\n i18n: 'extensions-servicem8',\n};\n\nconst MODULE_NAME = 'ServiceM8Extension';\n\nexport const RootConfig = {\n config,\n module: {\n name: MODULE_NAME,\n title: `@${config.i18n}:integration.display-name`,\n icon: 'fa-light fa-briefcase',\n },\n};\n\n//#endregion\n","//#region ---- Command Keys ----\n\nexport const AXEServiceM8CommandKeys = {\n ConnectionConnect: 'servicem8-extension.Connection:Connect',\n ConnectionCompleteOAuth: 'servicem8-extension.Connection:CompleteOAuth',\n ConnectionLifecycle: 'servicem8-extension.Connection:Lifecycle',\n OAuthStart: 'servicem8-extension.OAuth:Start',\n OAuthComplete: 'servicem8-extension.OAuth:Complete',\n OAuthValidate: 'servicem8-extension.OAuth:Validate',\n ProjectImportFromServiceM8: 'servicem8-extension.Project:ImportFromServiceM8',\n CustomerImportFromServiceM8: 'servicem8-extension.Customer:ImportFromServiceM8',\n ProjectSync: 'servicem8-extension.Project:Sync',\n JobsPull: 'servicem8-extension.Jobs:Pull',\n JobsRefresh: 'servicem8-extension.Jobs:Refresh',\n} as const;\n\n//#endregion\n","//#region ---- Menu Keys ----\n\nexport const AXEServiceM8MenuKeys = {\n ServiceM8ExtensionConfig: 'servicem8-extension:Menu:Configuration',\n} as const;\n\n//#endregion\n","//#region ---- Permission Keys ----\n\n/**\n * Administration capabilities used by this extension.\n * Domain capability keys for this module. Root groups live in `AXPCommonPermissionGroupKeys` (common contracts).\n */\nexport const AXPAdministrationPermissionKeys = {\n Access: 'Administration:Permission:Access',\n MaintainUsersAndRoles: 'Administration:Permission:MaintainUsersAndRoles',\n ManageSessions: 'Administration:Permission:ManageSessions',\n MaintainPolicies: 'Administration:Permission:MaintainPolicies',\n ViewIntegrations: 'Administration:Permission:ViewIntegrations',\n MaintainConnections: 'Administration:Permission:MaintainConnections',\n ManageIntegrationActions: 'Administration:Permission:ManageIntegrationActions',\n MaintainWorkflows: 'Administration:Permission:MaintainWorkflows',\n ManageWorkflowActions: 'Administration:Permission:ManageWorkflowActions',\n ViewRules: 'Administration:Permission:ViewRules',\n MaintainRules: 'Administration:Permission:MaintainRules',\n ManageRuleActions: 'Administration:Permission:ManageRuleActions',\n MaintainAi: 'Administration:Permission:MaintainAi',\n UseAiAssist: 'Administration:Permission:UseAiAssist',\n MaintainDashboards: 'Administration:Permission:MaintainDashboards',\n ViewJobs: 'Administration:Permission:ViewJobs',\n ManageJobActions: 'Administration:Permission:ManageJobActions',\n ViewObservability: 'Administration:Permission:ViewObservability',\n MaintainObservability: 'Administration:Permission:MaintainObservability',\n} as const;\n\n/**\n * @deprecated Prefer {@link AXPAdministrationPermissionKeys}.\n * Legacy nested shape kept so existing imports compile during migration.\n */\nexport const AXEServiceM8Permissions = {\n ServiceM8Extension: {\n Management: AXPAdministrationPermissionKeys.MaintainConnections,\n Catalog: {\n View: AXPAdministrationPermissionKeys.ViewIntegrations,\n },\n ProjectImport: {\n Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,\n },\n CustomerImport: {\n Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,\n },\n ProjectSync: {\n Execute: AXPAdministrationPermissionKeys.ManageIntegrationActions,\n },\n },\n} as const;\n\n//#endregion\n","//#region ---- ServiceM8 tenant connection config ----\n\n/** Stored on IntegrationManagement connection `config` for tenant-scoped ServiceM8. */\nexport interface AXEServiceM8ConnectionConfig {\n /** OAuth2 App ID from the ServiceM8 developer add-on. */\n clientId?: string;\n /** OAuth2 App Secret from the ServiceM8 developer add-on. */\n clientSecret?: string;\n /** Space-separated scopes granted at authorize time. */\n scope?: string;\n /** Current bearer token (authorization-code flow). */\n accessToken?: string;\n /** Refresh token from ServiceM8 token response. */\n refreshToken?: string;\n /** ISO timestamp when `accessToken` expires. */\n tokenExpiresAt?: string;\n /** Full ServiceM8 token JSON response. */\n oauthTokenJson?: string;\n /** Background job pull sync state (server-managed). */\n jobsSync?: AXEServiceM8JobsSyncState;\n}\n\n/** ServiceM8 job pull sync state stored on the tenant connection `config.jobsSync`. */\nexport interface AXEServiceM8JobsSyncState {\n /** ISO timestamp — last successful job pull (incremental sync watermark). */\n lastSyncAt?: string;\n /** ISO timestamp — last full snapshot reconcile (deactivation pass). */\n lastFullReconcileAt?: string;\n}\n\n//#endregion\n","//#region ---- ServiceM8 OAuth API (client ↔ server) ----\n\nexport interface AXEServiceM8OAuthStartRequest {\n redirectUri: string;\n connectionId?: string;\n}\n\nexport interface AXEServiceM8OAuthStartResponse {\n redirectUrl: string;\n state: string;\n}\n\nexport interface AXEServiceM8OAuthCompleteRequest {\n state: string;\n code: string;\n}\n\nexport interface AXEServiceM8OAuthCompleteResponse {\n connectionId: string;\n}\n\nexport interface AXEServiceM8OAuthValidateRequest {\n connectionId?: string;\n}\n\nexport interface AXEServiceM8OAuthValidateResponse {\n valid: boolean;\n message?: string;\n}\n\n//#endregion\n","//#region ---- Remote ServiceM8 DTOs ----\n\nimport type { AXEServiceM8ProjectSyncStrategy } from './sync.types';\n\n/** Subset of ServiceM8 `job.json` fields used for cache / import / sync. */\nexport interface AXEServiceM8RemoteJob {\n uuid: string;\n generated_job_id?: string | null;\n job_description?: string | null;\n job_address?: string | null;\n status?: string | null;\n date?: string | null;\n edit_date?: string | null;\n company_uuid?: string | null;\n company_name?: string | null;\n purchase_order_number?: string | null;\n active?: number | boolean | null;\n billing_address?: string | null;\n work_done_description?: string | null;\n}\n\n/**\n * ServiceM8 company (client) — cached as `resourceType=customer`.\n * Includes ServiceM8 address fields plus optional Simpro-shaped aliases when present.\n */\nexport interface AXEServiceM8RemoteCustomer {\n uuid: string;\n name?: string | null;\n address?: string | null;\n address_street?: string | null;\n address_city?: string | null;\n address_state?: string | null;\n address_postcode?: string | null;\n address_country?: string | null;\n fax_number?: string | null;\n FamilyName?: string | null;\n Phone?: string | null;\n Email?: string | null;\n EIN?: string | null;\n CompanyName?: string | null;\n active?: number | boolean | null;\n edit_date?: string | null;\n}\n\n/** ServiceM8 companycontact — cached as `resourceType=site`. */\nexport interface AXEServiceM8RemoteSite {\n uuid: string;\n company_uuid?: string | null;\n first?: string | null;\n last?: string | null;\n phone?: string | null;\n mobile?: string | null;\n email?: string | null;\n type?: string | null;\n active?: number | boolean | null;\n edit_date?: string | null;\n}\n\n//#endregion\n\n//#region ---- API request / response ----\n\nexport interface AXEServiceM8PullJobsRequest {\n /** When set, pulls for this ServiceM8 connection (required for multi-connection schedules). */\n connectionId?: string;\n /** Maximum ServiceM8 jobs to pull into the cache (default 250, max 1000). */\n maxJobs?: number;\n /**\n * When true, runs a full snapshot (no incremental filter) and reconciles deactivations.\n * When false (default for schedules), pulls jobs modified since the last successful sync.\n */\n force?: boolean;\n}\n\nexport interface AXEServiceM8PullJobsResponse {\n upserted: number;\n deactivated: number;\n /** True when incremental pull found no modified jobs in ServiceM8. */\n skipped?: boolean;\n /** Whether this run used incremental or full snapshot mode. */\n syncMode?: 'incremental' | 'full';\n /** Per data-type upsert counts (jobs / customers / sites). */\n byResourceType?: {\n job?: { upserted: number; deactivated: number };\n customer?: { upserted: number; deactivated: number };\n site?: { upserted: number; deactivated: number };\n };\n}\n\nexport interface AXEServiceM8ImportJobRequest {\n remoteRecordId: string;\n projectTypeId: string;\n syncStrategy: AXEServiceM8ProjectSyncStrategy;\n}\n\nexport interface AXEServiceM8ImportJobResponse {\n platformProjectId: string;\n created: boolean;\n}\n\nexport interface AXEServiceM8ImportCustomerRequest {\n remoteRecordId: string;\n}\n\nexport interface AXEServiceM8ImportCustomerResponse {\n platformCustomerId: string;\n created: boolean;\n}\n\nexport interface AXEServiceM8SyncPlatformProjectRequest {\n platformProjectId: string;\n}\n\nexport interface AXEServiceM8ConnectionLifecycleRequest {\n connectionId: string;\n action: 'connected' | 'disconnected' | 'deleted' | 'enabled' | 'disabled';\n}\n\nexport interface AXEServiceM8ConnectionLifecycleResponse {\n ok: true;\n}\n\n//#endregion\n","//#region ---- ServiceM8 API / OAuth constants ----\n\n/** Public OAuth authorize endpoint (fixed host). */\nexport const AXE_SERVICEM8_OAUTH_AUTHORIZE_URL = 'https://go.servicem8.com/oauth/authorize';\n\n/** Public OAuth token endpoint (authorization_code + refresh_token). */\nexport const AXE_SERVICEM8_OAUTH_TOKEN_URL = 'https://go.servicem8.com/oauth/access_token';\n\n/** REST API base URL stored on connection `instanceUrl`. */\nexport const AXE_SERVICEM8_API_BASE_URL = 'https://api.servicem8.com';\n\n/**\n * OAuth scopes for connect / authorize.\n * Space-separated; encoded as `scope=` query value by the OAuth start flow.\n */\nexport const AXE_SERVICEM8_OAUTH_SCOPES =\n 'read_customers read_jobs read_staff read_job_contacts read_job_attachments publish_job_attachments read_customer_contacts';\n\n//#endregion\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAAA;AAEA,MAAM,MAAM,GAAG;AACb,IAAA,IAAI,EAAE,sBAAsB;CAC7B;AAED,MAAM,WAAW,GAAG,oBAAoB;AAEjC,MAAM,UAAU,GAAG;IACxB,MAAM;AACN,IAAA,MAAM,EAAE;AACN,QAAA,IAAI,EAAE,WAAW;AACjB,QAAA,KAAK,EAAE,CAAA,CAAA,EAAI,MAAM,CAAC,IAAI,CAAA,yBAAA,CAA2B;AACjD,QAAA,IAAI,EAAE,uBAAuB;AAC9B,KAAA;;AAGH;;ACjBA;AAEO,MAAM,uBAAuB,GAAG;AACrC,IAAA,iBAAiB,EAAE,wCAAwC;AAC3D,IAAA,uBAAuB,EAAE,8CAA8C;AACvE,IAAA,mBAAmB,EAAE,0CAA0C;AAC/D,IAAA,UAAU,EAAE,iCAAiC;AAC7C,IAAA,aAAa,EAAE,oCAAoC;AACnD,IAAA,aAAa,EAAE,oCAAoC;AACnD,IAAA,0BAA0B,EAAE,iDAAiD;AAC7E,IAAA,2BAA2B,EAAE,kDAAkD;AAC/E,IAAA,WAAW,EAAE,kCAAkC;AAC/C,IAAA,QAAQ,EAAE,+BAA+B;AACzC,IAAA,WAAW,EAAE,kCAAkC;;AAGjD;;AChBA;AAEO,MAAM,oBAAoB,GAAG;AAClC,IAAA,wBAAwB,EAAE,wCAAwC;;AAGpE;;ACNA;AAEA;;;AAGG;AACI,MAAM,+BAA+B,GAAG;AAC7C,IAAA,MAAM,EAAE,kCAAkC;AAC1C,IAAA,qBAAqB,EAAE,iDAAiD;AACxE,IAAA,cAAc,EAAE,0CAA0C;AAC1D,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,mBAAmB,EAAE,+CAA+C;AACpE,IAAA,wBAAwB,EAAE,oDAAoD;AAC9E,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,qBAAqB,EAAE,iDAAiD;AACxE,IAAA,SAAS,EAAE,qCAAqC;AAChD,IAAA,aAAa,EAAE,yCAAyC;AACxD,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,UAAU,EAAE,sCAAsC;AAClD,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,kBAAkB,EAAE,8CAA8C;AAClE,IAAA,QAAQ,EAAE,oCAAoC;AAC9C,IAAA,gBAAgB,EAAE,4CAA4C;AAC9D,IAAA,iBAAiB,EAAE,6CAA6C;AAChE,IAAA,qBAAqB,EAAE,iDAAiD;;AAG1E;;;AAGG;AACI,MAAM,uBAAuB,GAAG;AACrC,IAAA,kBAAkB,EAAE;QAClB,UAAU,EAAE,+BAA+B,CAAC,mBAAmB;AAC/D,QAAA,OAAO,EAAE;YACP,IAAI,EAAE,+BAA+B,CAAC,gBAAgB;AACvD,SAAA;AACD,QAAA,aAAa,EAAE;YACb,OAAO,EAAE,+BAA+B,CAAC,wBAAwB;AAClE,SAAA;AACD,QAAA,cAAc,EAAE;YACd,OAAO,EAAE,+BAA+B,CAAC,wBAAwB;AAClE,SAAA;AACD,QAAA,WAAW,EAAE;YACX,OAAO,EAAE,+BAA+B,CAAC,wBAAwB;AAClE,SAAA;AACF,KAAA;;AAGH;;AClDA;AA8BA;;AC9BA;AA8BA;;AC9BA;AA0HA;;AC1HA;AAEA;AACO,MAAM,iCAAiC,GAAG;AAEjD;AACO,MAAM,6BAA6B,GAAG;AAE7C;AACO,MAAM,0BAA0B,GAAG;AAE1C;;;AAGG;AACI,MAAM,0BAA0B,GACrC;AAEF;;AClBA;;AAEG;;;;"}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { AXMIntegrationManagementModule } from '@acorex-platform/module-integration-management-client';
|
|
2
|
-
import { AXPIntegrationRuntimeService, AXP_INTEGRATION_SECRET_STORE, AXPSettingsService, AXP_INTEGRATION_RUNTIME_PROVIDER, AXP_MENU_PROVIDER, AXP_INTEGRATION_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
2
|
+
import { AXPIntegrationRuntimeService, AXP_INTEGRATION_SECRET_STORE, AXPSettingsService, AXP_INTEGRATION_RUNTIME_PROVIDER, AXP_INTEGRATION_CONNECTION_LIFECYCLE, AXP_MENU_PROVIDER, AXP_INTEGRATION_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
3
3
|
import { AXP_LOGO_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER } from '@acorex-platform/framework-client/core';
|
|
4
4
|
import { AXPEntityService, ensureListActions, actionExists, AXP_ENTITY_MODIFIER } from '@acorex-platform/framework-client/layout/entity';
|
|
5
|
-
import { provideCommandSetups } from '@acorex-platform/framework-client/runtime';
|
|
5
|
+
import { AXPQueryService, AXPCommandService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { inject, Injectable, NgModule } from '@angular/core';
|
|
8
|
-
import { AXEServiceM8CommandKeys, RootConfig as RootConfig$
|
|
8
|
+
import { AXEServiceM8CommandKeys, RootConfig as RootConfig$2, AXPAdministrationPermissionKeys, AXEServiceM8MenuKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';
|
|
9
9
|
import { AXE_PM_INTEGRATION_PROVIDER_SERVICEM8 } from '@acorex-platform/extension-project-management-core-client/contracts';
|
|
10
10
|
import { RootConfig } from '@acorex-platform/module-project-management-client/contracts';
|
|
11
|
-
import { AXPSystemActionType, AXPWidgetsList, AXP_INTEGRATION_AUTH_METHOD_TYPE, AXP_INTEGRATION_CONNECTION_SCOPE, AXP_INTEGRATION_CAPABILITY, AXPRegionalSetting, AXP_INTEGRATION_CONNECTION_STATUS } from '@acorex-platform/framework-shared/core';
|
|
11
|
+
import { AXPSystemActionType, AXPWidgetsList, AXP_INTEGRATION_AUTH_METHOD_TYPE, AXP_INTEGRATION_CONNECTION_SCOPE, AXP_INTEGRATION_CAPABILITY, AXPRegionalSetting, AXP_INTEGRATION_CONNECTION_STATUS, runtimeQueryPayloadData } from '@acorex-platform/framework-shared/core';
|
|
12
12
|
import { AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';
|
|
13
|
+
import { AXEServiceM8CommandKeys as AXEServiceM8CommandKeys$1 } from '@acorex-platform/extension-project-management-servicem8-client/contracts';
|
|
14
|
+
import { RootConfig as RootConfig$1 } from '@acorex-platform/module-customer-management-client/contracts';
|
|
13
15
|
import { AXFormatService } from '@acorex/core/format';
|
|
14
16
|
import { trim, defaultTo } from 'lodash-es';
|
|
17
|
+
import { AXPBackgroundJobQueryKeys } from '@acorex-platform/framework-shared/background-job';
|
|
15
18
|
import { AXPCommonMenuKeys } from '@acorex-platform/module-common-client/contracts';
|
|
16
19
|
|
|
17
20
|
const AXE_SERVICEM8_EXPRESSION_SCOPE = 'ServiceM8Extension';
|
|
@@ -52,9 +55,9 @@ class AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider {
|
|
|
52
55
|
|
|
53
56
|
//#region ---- Imports ----
|
|
54
57
|
//#endregion
|
|
55
|
-
const IMPORT_ORDER = 36;
|
|
58
|
+
const IMPORT_ORDER$1 = 36;
|
|
56
59
|
const SYNC_ORDER = 37;
|
|
57
|
-
function buildImportAction() {
|
|
60
|
+
function buildImportAction$1() {
|
|
58
61
|
return {
|
|
59
62
|
name: AXEServiceM8CommandKeys.ProjectImportFromServiceM8,
|
|
60
63
|
title: '@extensions-servicem8:actions.import-from-servicem8.title',
|
|
@@ -63,7 +66,7 @@ function buildImportAction() {
|
|
|
63
66
|
type: AXPSystemActionType.Import,
|
|
64
67
|
icon: 'fa-light fa-briefcase',
|
|
65
68
|
scope: AXPEntityCommandScope.TypeLevel,
|
|
66
|
-
order: IMPORT_ORDER,
|
|
69
|
+
order: IMPORT_ORDER$1,
|
|
67
70
|
};
|
|
68
71
|
}
|
|
69
72
|
function buildSyncAction() {
|
|
@@ -97,7 +100,7 @@ const AXEServiceM8ProjectEntityModifier = {
|
|
|
97
100
|
const list = (master['list'] ?? { actions: [], views: [] });
|
|
98
101
|
const listActions = (list['actions'] ?? []);
|
|
99
102
|
if (!actionExists(listActions, AXEServiceM8CommandKeys.ProjectImportFromServiceM8)) {
|
|
100
|
-
listActions.push(buildImportAction());
|
|
103
|
+
listActions.push(buildImportAction$1());
|
|
101
104
|
}
|
|
102
105
|
list['actions'] = listActions;
|
|
103
106
|
master['list'] = list;
|
|
@@ -116,6 +119,50 @@ const AXEServiceM8ProjectEntityModifier = {
|
|
|
116
119
|
};
|
|
117
120
|
//#endregion
|
|
118
121
|
|
|
122
|
+
//#region ---- Imports ----
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region ----- Constants -----
|
|
125
|
+
const IMPORT_ORDER = 36;
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region ----- Actions -----
|
|
128
|
+
function buildImportAction() {
|
|
129
|
+
return {
|
|
130
|
+
name: AXEServiceM8CommandKeys$1.CustomerImportFromServiceM8,
|
|
131
|
+
title: '@extensions-servicem8:actions.import-from-servicem8.title',
|
|
132
|
+
command: { name: AXEServiceM8CommandKeys$1.CustomerImportFromServiceM8 },
|
|
133
|
+
priority: 'secondary',
|
|
134
|
+
type: AXPSystemActionType.Import,
|
|
135
|
+
icon: 'fa-light fa-briefcase',
|
|
136
|
+
scope: AXPEntityCommandScope.TypeLevel,
|
|
137
|
+
order: IMPORT_ORDER,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region ----- Modifier -----
|
|
142
|
+
/** Adds ServiceM8 import action to CustomerManagement.Customer list views. */
|
|
143
|
+
const AXEServiceM8CustomerEntityModifier = {
|
|
144
|
+
entityName: RootConfig$1.entities.customer.name,
|
|
145
|
+
order: 50,
|
|
146
|
+
modifier: (ctx) => {
|
|
147
|
+
if (ctx.module.get() !== RootConfig$1.module.name) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
ensureListActions(ctx);
|
|
151
|
+
ctx.interfaces.master.list.update((list) => {
|
|
152
|
+
const next = list ?? { actions: [], views: [] };
|
|
153
|
+
const listActions = [...(next.actions ?? [])];
|
|
154
|
+
if (!actionExists(listActions, AXEServiceM8CommandKeys$1.CustomerImportFromServiceM8)) {
|
|
155
|
+
listActions.push(buildImportAction());
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
...next,
|
|
159
|
+
actions: listActions,
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
//#endregion
|
|
165
|
+
|
|
119
166
|
//#region ---- ServiceM8 logo registry key ----
|
|
120
167
|
const axpServiceM8LogoKey = 'servicem8';
|
|
121
168
|
/** Mark artwork (1024×1024); consuming apps copy to `assets/images/brand/integrations/`. */
|
|
@@ -126,14 +173,14 @@ const AXE_SERVICEM8_MARK_ASPECT = 1;
|
|
|
126
173
|
|
|
127
174
|
class AXEServiceM8IntegrationProvider {
|
|
128
175
|
async provide(context) {
|
|
129
|
-
const I18N = `@${RootConfig$
|
|
176
|
+
const I18N = `@${RootConfig$2.config.i18n}:integration`;
|
|
130
177
|
context.register({
|
|
131
178
|
domainId: 'project-management',
|
|
132
179
|
id: 'servicem8',
|
|
133
|
-
module: RootConfig$
|
|
180
|
+
module: RootConfig$2.module.name,
|
|
134
181
|
displayName: `${I18N}.display-name`,
|
|
135
182
|
description: `${I18N}.description`,
|
|
136
|
-
icon: RootConfig$
|
|
183
|
+
icon: RootConfig$2.module.icon,
|
|
137
184
|
logoKey: axpServiceM8LogoKey,
|
|
138
185
|
capabilities: [AXP_INTEGRATION_CAPABILITY.Sync, AXP_INTEGRATION_CAPABILITY.Import],
|
|
139
186
|
connectionScopes: [AXP_INTEGRATION_CONNECTION_SCOPE.Tenant],
|
|
@@ -175,6 +222,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
175
222
|
|
|
176
223
|
//#region ---- ServiceM8 integration settings badges ----
|
|
177
224
|
const SERVICEM8_I18N = '@extensions-servicem8:integration.badges';
|
|
225
|
+
/** Must match `SERVICEM8_PULL_JOBS_COMMAND_KEY` / schedule `command.key`. */
|
|
226
|
+
const SERVICEM8_PULL_JOBS_SCHEDULE_COMMAND_KEY = 'servicem8-extension.jobs.pull';
|
|
178
227
|
async function formatSyncTimestamp(iso, formatService, settingsService) {
|
|
179
228
|
const parsed = Date.parse(iso);
|
|
180
229
|
if (!Number.isFinite(parsed)) {
|
|
@@ -185,30 +234,75 @@ async function formatSyncTimestamp(iso, formatService, settingsService) {
|
|
|
185
234
|
const format = `${dateFormat} ${timeFormat}`.trim();
|
|
186
235
|
return formatService.format(new Date(parsed), 'datetime', { format });
|
|
187
236
|
}
|
|
188
|
-
|
|
237
|
+
function isFailureNewer(schedule) {
|
|
238
|
+
const failed = schedule.lastFailureAt ? Date.parse(schedule.lastFailureAt) : NaN;
|
|
239
|
+
const succeeded = schedule.lastSuccessAt ? Date.parse(schedule.lastSuccessAt) : NaN;
|
|
240
|
+
if (!Number.isFinite(failed)) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (!Number.isFinite(succeeded)) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
return failed >= succeeded;
|
|
247
|
+
}
|
|
248
|
+
async function resolveServiceM8ConnectionSettingsBadges(ctx, formatService, settingsService, schedule) {
|
|
189
249
|
const config = (ctx.connection.config ?? {});
|
|
190
250
|
const jobsSync = config.jobsSync;
|
|
191
251
|
const lastSync = config.jobsSync?.lastSyncAt?.trim() ||
|
|
192
252
|
(typeof jobsSync?.['lastSuccessfulSyncAt'] === 'string' ? jobsSync['lastSuccessfulSyncAt'].trim() : '');
|
|
253
|
+
const badges = [];
|
|
193
254
|
if (!lastSync) {
|
|
194
|
-
|
|
195
|
-
{
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
},
|
|
199
|
-
];
|
|
255
|
+
badges.push({
|
|
256
|
+
labelKey: `${SERVICEM8_I18N}.never-synced`,
|
|
257
|
+
color: 'warning',
|
|
258
|
+
});
|
|
200
259
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
260
|
+
else {
|
|
261
|
+
const datetime = await formatSyncTimestamp(lastSync, formatService, settingsService);
|
|
262
|
+
if (datetime) {
|
|
263
|
+
badges.push({
|
|
264
|
+
labelKey: `${SERVICEM8_I18N}.last-sync`,
|
|
265
|
+
params: { datetime },
|
|
266
|
+
color: 'success',
|
|
267
|
+
});
|
|
268
|
+
}
|
|
204
269
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
270
|
+
if (!schedule) {
|
|
271
|
+
return badges;
|
|
272
|
+
}
|
|
273
|
+
if (schedule.status === 'pause') {
|
|
274
|
+
badges.push({
|
|
275
|
+
labelKey: `${SERVICEM8_I18N}.schedule-paused`,
|
|
276
|
+
color: 'warning',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
else if (schedule.status === 'disabled') {
|
|
280
|
+
badges.push({
|
|
281
|
+
labelKey: `${SERVICEM8_I18N}.schedule-disabled`,
|
|
282
|
+
color: 'warning',
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
if (schedule.nextRunAt) {
|
|
286
|
+
const datetime = await formatSyncTimestamp(schedule.nextRunAt, formatService, settingsService);
|
|
287
|
+
if (datetime) {
|
|
288
|
+
badges.push({
|
|
289
|
+
labelKey: `${SERVICEM8_I18N}.next-run`,
|
|
290
|
+
params: { datetime },
|
|
291
|
+
color: 'secondary',
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (isFailureNewer(schedule) && schedule.lastFailureAt) {
|
|
296
|
+
const datetime = await formatSyncTimestamp(schedule.lastFailureAt, formatService, settingsService);
|
|
297
|
+
if (datetime) {
|
|
298
|
+
badges.push({
|
|
299
|
+
labelKey: `${SERVICEM8_I18N}.last-failure`,
|
|
300
|
+
params: { datetime },
|
|
301
|
+
color: 'danger',
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return badges;
|
|
212
306
|
}
|
|
213
307
|
//#endregion
|
|
214
308
|
|
|
@@ -218,12 +312,13 @@ class AXEServiceM8IntegrationRuntimeProvider {
|
|
|
218
312
|
this.secretStore = inject(AXP_INTEGRATION_SECRET_STORE, { optional: true });
|
|
219
313
|
this.formatService = inject(AXFormatService);
|
|
220
314
|
this.settingsService = inject(AXPSettingsService);
|
|
315
|
+
this.queryService = inject(AXPQueryService, { optional: true });
|
|
221
316
|
}
|
|
222
317
|
async getHooks() {
|
|
223
318
|
return {
|
|
224
319
|
validateConnection: (ctx) => this.validateConnection(ctx),
|
|
225
320
|
createClient: (ctx) => this.createClient(ctx),
|
|
226
|
-
getConnectionSettingsBadges: (ctx) => resolveServiceM8ConnectionSettingsBadges(ctx, this.formatService, this.settingsService),
|
|
321
|
+
getConnectionSettingsBadges: async (ctx) => resolveServiceM8ConnectionSettingsBadges(ctx, this.formatService, this.settingsService, await this.loadPullSchedule(ctx.connection.id)),
|
|
227
322
|
};
|
|
228
323
|
}
|
|
229
324
|
async validateConnection(ctx) {
|
|
@@ -273,6 +368,21 @@ class AXEServiceM8IntegrationRuntimeProvider {
|
|
|
273
368
|
}
|
|
274
369
|
return { clientId, clientSecret };
|
|
275
370
|
}
|
|
371
|
+
async loadPullSchedule(connectionId) {
|
|
372
|
+
if (!this.queryService || !connectionId.trim()) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
const result = await this.queryService.fetch(AXPBackgroundJobQueryKeys.ScheduleGetByScope, {
|
|
377
|
+
commandKey: SERVICEM8_PULL_JOBS_SCHEDULE_COMMAND_KEY,
|
|
378
|
+
connectionId,
|
|
379
|
+
});
|
|
380
|
+
return runtimeQueryPayloadData(result) ?? null;
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
276
386
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEServiceM8IntegrationRuntimeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
277
387
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEServiceM8IntegrationRuntimeProvider }); }
|
|
278
388
|
}
|
|
@@ -285,6 +395,47 @@ const provideServiceM8IntegrationRuntimeProvider = {
|
|
|
285
395
|
multi: true,
|
|
286
396
|
};
|
|
287
397
|
|
|
398
|
+
//#region ---- Imports ----
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region ---- Handler ----
|
|
401
|
+
class AXEServiceM8ConnectionLifecycleHandler {
|
|
402
|
+
constructor() {
|
|
403
|
+
this.providerId = 'servicem8';
|
|
404
|
+
this.commandService = inject(AXPCommandService);
|
|
405
|
+
}
|
|
406
|
+
async onDisconnected(connection) {
|
|
407
|
+
await this.runLifecycle(connection.id, 'disconnected');
|
|
408
|
+
}
|
|
409
|
+
async onDeleted(connection) {
|
|
410
|
+
await this.runLifecycle(connection.id, 'deleted');
|
|
411
|
+
}
|
|
412
|
+
async onEnabledChanged(connection, enabled) {
|
|
413
|
+
if (enabled) {
|
|
414
|
+
if (connection.status === AXP_INTEGRATION_CONNECTION_STATUS.Connected) {
|
|
415
|
+
await this.runLifecycle(connection.id, 'enabled');
|
|
416
|
+
}
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
await this.runLifecycle(connection.id, 'disabled');
|
|
420
|
+
}
|
|
421
|
+
async runLifecycle(connectionId, action) {
|
|
422
|
+
await this.commandService.execute(AXEServiceM8CommandKeys$1.ConnectionLifecycle, {
|
|
423
|
+
connectionId,
|
|
424
|
+
action,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEServiceM8ConnectionLifecycleHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
428
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEServiceM8ConnectionLifecycleHandler }); }
|
|
429
|
+
}
|
|
430
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEServiceM8ConnectionLifecycleHandler, decorators: [{
|
|
431
|
+
type: Injectable
|
|
432
|
+
}] });
|
|
433
|
+
const provideServiceM8ConnectionLifecycleHandler = {
|
|
434
|
+
provide: AXP_INTEGRATION_CONNECTION_LIFECYCLE,
|
|
435
|
+
useClass: AXEServiceM8ConnectionLifecycleHandler,
|
|
436
|
+
multi: true,
|
|
437
|
+
};
|
|
438
|
+
|
|
288
439
|
const servicem8LogoProvider = {
|
|
289
440
|
key: axpServiceM8LogoKey,
|
|
290
441
|
resolve: async (request) => ({
|
|
@@ -302,11 +453,11 @@ const AXE_SERVICEM8_LOGO_PROVIDER = {
|
|
|
302
453
|
|
|
303
454
|
//#region ---- Manifest ----
|
|
304
455
|
const ServiceM8ExtensionManifest = {
|
|
305
|
-
name: RootConfig$
|
|
456
|
+
name: RootConfig$2.module.name,
|
|
306
457
|
version: '1.0.0',
|
|
307
|
-
title: RootConfig$
|
|
308
|
-
icon: RootConfig$
|
|
309
|
-
i18n: RootConfig$
|
|
458
|
+
title: RootConfig$2.module.title,
|
|
459
|
+
icon: RootConfig$2.module.icon,
|
|
460
|
+
i18n: RootConfig$2.config.i18n,
|
|
310
461
|
type: 'integration',
|
|
311
462
|
domain: 'project-management',
|
|
312
463
|
dependencies: [],
|
|
@@ -317,7 +468,7 @@ const ServiceM8ExtensionManifest = {
|
|
|
317
468
|
//#endregion
|
|
318
469
|
class AXEServiceM8MenuProvider {
|
|
319
470
|
async provide(context) {
|
|
320
|
-
const module = RootConfig$
|
|
471
|
+
const module = RootConfig$2.module;
|
|
321
472
|
const policy = {
|
|
322
473
|
features: [module.name],
|
|
323
474
|
permissions: [AXPAdministrationPermissionKeys.MaintainConnections],
|
|
@@ -354,6 +505,7 @@ class AXEServiceM8ExtensionModule {
|
|
|
354
505
|
{ provide: AXP_MODULE_MANIFEST_PROVIDER, useValue: ServiceM8ExtensionManifest, multi: true },
|
|
355
506
|
{ provide: AXP_MENU_PROVIDER, useClass: AXEServiceM8MenuProvider, multi: true },
|
|
356
507
|
{ provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8ProjectEntityModifier, multi: true },
|
|
508
|
+
{ provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8CustomerEntityModifier, multi: true },
|
|
357
509
|
{
|
|
358
510
|
provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
|
|
359
511
|
useClass: AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider,
|
|
@@ -361,10 +513,11 @@ class AXEServiceM8ExtensionModule {
|
|
|
361
513
|
},
|
|
362
514
|
{ provide: AXP_INTEGRATION_PROVIDER, useClass: AXEServiceM8IntegrationProvider, multi: true },
|
|
363
515
|
provideServiceM8IntegrationRuntimeProvider,
|
|
516
|
+
provideServiceM8ConnectionLifecycleHandler,
|
|
364
517
|
provideCommandSetups([
|
|
365
518
|
{
|
|
366
519
|
key: AXEServiceM8CommandKeys.ConnectionConnect,
|
|
367
|
-
command: () => import('./acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-
|
|
520
|
+
command: () => import('./acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs').then((c) => c.ConnectServiceM8Command),
|
|
368
521
|
},
|
|
369
522
|
{
|
|
370
523
|
key: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,
|
|
@@ -382,6 +535,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
382
535
|
{ provide: AXP_MODULE_MANIFEST_PROVIDER, useValue: ServiceM8ExtensionManifest, multi: true },
|
|
383
536
|
{ provide: AXP_MENU_PROVIDER, useClass: AXEServiceM8MenuProvider, multi: true },
|
|
384
537
|
{ provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8ProjectEntityModifier, multi: true },
|
|
538
|
+
{ provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8CustomerEntityModifier, multi: true },
|
|
385
539
|
{
|
|
386
540
|
provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
|
|
387
541
|
useClass: AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider,
|
|
@@ -389,10 +543,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
389
543
|
},
|
|
390
544
|
{ provide: AXP_INTEGRATION_PROVIDER, useClass: AXEServiceM8IntegrationProvider, multi: true },
|
|
391
545
|
provideServiceM8IntegrationRuntimeProvider,
|
|
546
|
+
provideServiceM8ConnectionLifecycleHandler,
|
|
392
547
|
provideCommandSetups([
|
|
393
548
|
{
|
|
394
549
|
key: AXEServiceM8CommandKeys.ConnectionConnect,
|
|
395
|
-
command: () => import('./acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-
|
|
550
|
+
command: () => import('./acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-3MmHke4f.mjs').then((c) => c.ConnectServiceM8Command),
|
|
396
551
|
},
|
|
397
552
|
{
|
|
398
553
|
key: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client.mjs","sources":["../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/servicem8-expression-scope.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/servicem8-project-link-expression-evaluator-scope.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/project-servicem8.entity-modifier.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/brand/servicem8-logo-key.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8.integration.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8-integration-settings-badges.util.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8.integration-runtime.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/brand/servicem8-logo.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/manifest.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/menu.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/servicem8-extension.module.ts","../../../../libs/extensions/project-management/servicem8/client/src/acorex-platform-extension-project-management-servicem8-client.ts"],"sourcesContent":["export const AXE_SERVICEM8_EXPRESSION_SCOPE = 'ServiceM8Extension';\n","//#region ---- Imports ----\n\nimport { AXPExpressionEvaluatorScopeProvider, AXPExpressionEvaluatorScopeProviderContext } from '@acorex-platform/framework-shared/core';\nimport { AXPIntegrationRuntimeService } from '@acorex-platform/framework-client/common';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { inject } from '@angular/core';\nimport { AXE_PM_INTEGRATION_PROVIDER_SERVICEM8 } from '@acorex-platform/extension-project-management-core-client/contracts';\nimport { RootConfig as PmRootConfig } from '@acorex-platform/module-project-management-client/contracts';\nimport type { AXMProjectManagementProjectEntityModel } from '@acorex-platform/module-project-management-client/contracts';\nimport { AXE_SERVICEM8_EXPRESSION_SCOPE } from './servicem8-expression-scope';\n\n//#endregion\n\nexport class AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider implements AXPExpressionEvaluatorScopeProvider {\n private readonly entityService = inject(AXPEntityService);\n private readonly integrationRuntime = inject(AXPIntegrationRuntimeService);\n\n async provide(context: AXPExpressionEvaluatorScopeProviderContext): Promise<void> {\n context.addScope(AXE_SERVICEM8_EXPRESSION_SCOPE, {\n hasProjectLink: async (platformProjectIdRaw?: unknown): Promise<boolean> => {\n const platformProjectId = typeof platformProjectIdRaw === 'string' ? platformProjectIdRaw.trim() : '';\n if (!platformProjectId) {\n return false;\n }\n\n const project = (await this.entityService\n .withEntity(PmRootConfig.module.name, PmRootConfig.entities.project.name)\n .data<string, AXMProjectManagementProjectEntityModel>()\n .byKey(platformProjectId)) as AXMProjectManagementProjectEntityModel | null;\n\n return project?.integrationRef?.source === AXE_PM_INTEGRATION_PROVIDER_SERVICEM8;\n },\n hasServiceM8Connection: async (): Promise<boolean> => {\n try {\n await this.integrationRuntime.getConnection({ providerId: 'servicem8', connectionScope: 'tenant' });\n return true;\n } catch {\n return false;\n }\n },\n });\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXPSystemActionType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityAction, AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';\nimport {\n actionExists,\n AXPEntityModifierProvider,\n ensureListActions,\n} from '@acorex-platform/framework-client/layout/entity';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { RootConfig as PmRootConfig } from '@acorex-platform/module-project-management-client/contracts';\nimport { AXE_SERVICEM8_EXPRESSION_SCOPE } from './servicem8-expression-scope';\n\n//#endregion\n\nconst IMPORT_ORDER = 36;\nconst SYNC_ORDER = 37;\n\nfunction buildImportAction(): AXPEntityAction {\n return {\n name: AXEServiceM8CommandKeys.ProjectImportFromServiceM8,\n title: '@extensions-servicem8:actions.import-from-servicem8.title',\n command: { name: AXEServiceM8CommandKeys.ProjectImportFromServiceM8 },\n priority: 'secondary',\n type: AXPSystemActionType.Import,\n icon: 'fa-light fa-briefcase',\n scope: AXPEntityCommandScope.TypeLevel,\n order: IMPORT_ORDER,\n };\n}\n\nfunction buildSyncAction(): AXPEntityAction {\n return {\n name: AXEServiceM8CommandKeys.ProjectSync,\n title: '@extensions-servicem8:actions.sync.title',\n command: {\n name: AXEServiceM8CommandKeys.ProjectSync,\n options: { platformProjectId: '{{ context.eval(\"id\") }}' },\n },\n priority: 'secondary',\n type: AXPSystemActionType.Sync,\n icon: 'fa-light fa-arrows-rotate',\n scope: AXPEntityCommandScope.Individual,\n order: SYNC_ORDER,\n hidden: `{{ !(await ${AXE_SERVICEM8_EXPRESSION_SCOPE}.hasProjectLink(context.eval(\"id\"))) }}`,\n };\n}\n\n/** Adds ServiceM8 import/sync actions to ProjectManagement.Project views. */\nexport const AXEServiceM8ProjectEntityModifier: AXPEntityModifierProvider = {\n entityName: PmRootConfig.entities.project.name,\n order: 50,\n modifier: (ctx) => {\n if (ctx.module.get() !== PmRootConfig.module.name) {\n return;\n }\n\n ensureListActions(ctx);\n\n ctx.interfaces.update((interfaces) => {\n const next = (interfaces ?? {}) as Record<string, unknown>;\n const master = (next['master'] ?? {}) as Record<string, unknown>;\n const list = (master['list'] ?? { actions: [], views: [] }) as Record<string, unknown>;\n const listActions = (list['actions'] ?? []) as AXPEntityAction[];\n\n if (!actionExists(listActions, AXEServiceM8CommandKeys.ProjectImportFromServiceM8)) {\n listActions.push(buildImportAction());\n }\n list['actions'] = listActions;\n master['list'] = list;\n\n const single = master['single'] as Record<string, unknown> | undefined;\n if (single) {\n const singleActions = (single['actions'] ?? []) as AXPEntityAction[];\n if (!actionExists(singleActions, AXEServiceM8CommandKeys.ProjectSync)) {\n singleActions.push(buildSyncAction());\n }\n single['actions'] = singleActions;\n }\n\n next['master'] = master;\n return next as typeof interfaces;\n });\n },\n};\n\n//#endregion\n","//#region ---- ServiceM8 logo registry key ----\n\nexport const axpServiceM8LogoKey = 'servicem8' as const;\n\n/** Mark artwork (1024×1024); consuming apps copy to `assets/images/brand/integrations/`. */\nexport const AXE_SERVICEM8_MARK_SRC = 'assets/images/brand/integrations/servicem8-mark.png';\n\n/** Source mark is square. */\nexport const AXE_SERVICEM8_MARK_ASPECT = 1;\n\n//#endregion\n","import {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n AXP_INTEGRATION_CAPABILITY,\n AXP_INTEGRATION_CONNECTION_SCOPE,\n AXPWidgetsList,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPIntegrationProvider, AXPIntegrationProviderContext } from '@acorex-platform/framework-client/common';\nimport { Injectable } from '@angular/core';\nimport { AXEServiceM8CommandKeys, RootConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { axpServiceM8LogoKey } from '../brand/servicem8-logo-key';\n\n@Injectable()\nexport class AXEServiceM8IntegrationProvider implements AXPIntegrationProvider {\n async provide(context: AXPIntegrationProviderContext): Promise<void> {\n const I18N = `@${RootConfig.config.i18n}:integration`;\n\n context.register({\n domainId: 'project-management',\n id: 'servicem8',\n module: RootConfig.module.name,\n displayName: `${I18N}.display-name`,\n description: `${I18N}.description`,\n icon: RootConfig.module.icon,\n logoKey: axpServiceM8LogoKey,\n capabilities: [AXP_INTEGRATION_CAPABILITY.Sync, AXP_INTEGRATION_CAPABILITY.Import],\n connectionScopes: [AXP_INTEGRATION_CONNECTION_SCOPE.Tenant],\n allowMultipleConnections: true,\n defaultConnectionKey: 'default',\n connectCommandKey: AXEServiceM8CommandKeys.ConnectionConnect,\n completeOAuthCommandKey: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,\n authMethods: [\n {\n type: AXP_INTEGRATION_AUTH_METHOD_TYPE.OAuth2,\n label: `${I18N}.auth.oauth.label`,\n instructions: `${I18N}.auth.oauth.instructions`,\n usesRedirect: false,\n supportsRefresh: true,\n supportsRevoke: false,\n supportsValidation: true,\n fields: [\n {\n type: AXPWidgetsList.Editors.TextBox,\n path: 'clientId',\n options: { placeholder: `${I18N}.auth.oauth.client-id.placeholder` },\n },\n {\n type: AXPWidgetsList.Editors.PasswordBox,\n path: 'clientSecret',\n options: { placeholder: `${I18N}.auth.oauth.client-secret.placeholder` },\n },\n ],\n },\n ],\n });\n }\n}\n","//#region ---- ServiceM8 integration settings badges ----\n\nimport { AXFormatService } from '@acorex/core/format';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';\nimport type {\n AXPIntegrationConnectionSettingsContext,\n AXPIntegrationSettingsRowBadge,\n} from '@acorex-platform/framework-shared/core';\nimport type { AXEServiceM8ConnectionConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\nconst SERVICEM8_I18N = '@extensions-servicem8:integration.badges';\n\nasync function formatSyncTimestamp(\n iso: string,\n formatService: AXFormatService,\n settingsService: AXPSettingsService,\n): Promise<string | undefined> {\n const parsed = Date.parse(iso);\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n\n const dateFormat = await settingsService.get(AXPRegionalSetting.ShortDate);\n const timeFormat = await settingsService.get(AXPRegionalSetting.ShortTime);\n const format = `${dateFormat} ${timeFormat}`.trim();\n\n return formatService.format(new Date(parsed), 'datetime', { format });\n}\n\nexport async function resolveServiceM8ConnectionSettingsBadges(\n ctx: AXPIntegrationConnectionSettingsContext,\n formatService: AXFormatService,\n settingsService: AXPSettingsService,\n): Promise<AXPIntegrationSettingsRowBadge[]> {\n const config = (ctx.connection.config ?? {}) as AXEServiceM8ConnectionConfig;\n const jobsSync = config.jobsSync as Record<string, unknown> | undefined;\n const lastSync =\n config.jobsSync?.lastSyncAt?.trim() ||\n (typeof jobsSync?.['lastSuccessfulSyncAt'] === 'string' ? jobsSync['lastSuccessfulSyncAt'].trim() : '');\n\n if (!lastSync) {\n return [\n {\n labelKey: `${SERVICEM8_I18N}.never-synced`,\n color: 'warning',\n },\n ];\n }\n\n const datetime = await formatSyncTimestamp(lastSync, formatService, settingsService);\n if (!datetime) {\n return [];\n }\n\n return [\n {\n labelKey: `${SERVICEM8_I18N}.last-sync`,\n params: { datetime },\n color: 'success',\n },\n ];\n}\n\n//#endregion\n","import {\n AXP_INTEGRATION_CONNECTION_STATUS,\n type AXPIntegrationProviderRuntimeHooks,\n type AXPIntegrationRuntimeContext,\n type AXPIntegrationValidationResult,\n} from '@acorex-platform/framework-shared/core';\nimport {\n AXP_INTEGRATION_RUNTIME_PROVIDER,\n AXP_INTEGRATION_SECRET_STORE,\n type AXPIntegrationRuntimeProvider,\n} from '@acorex-platform/framework-client/common';\nimport type { AXEServiceM8ConnectionConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { Injectable, inject } from '@angular/core';\nimport { AXFormatService } from '@acorex/core/format';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { defaultTo, trim } from 'lodash-es';\nimport { resolveServiceM8ConnectionSettingsBadges } from './servicem8-integration-settings-badges.util';\n\n@Injectable()\nexport class AXEServiceM8IntegrationRuntimeProvider implements AXPIntegrationRuntimeProvider {\n readonly providerId = 'servicem8';\n\n private readonly secretStore = inject(AXP_INTEGRATION_SECRET_STORE, { optional: true });\n private readonly formatService = inject(AXFormatService);\n private readonly settingsService = inject(AXPSettingsService);\n\n async getHooks(): Promise<AXPIntegrationProviderRuntimeHooks> {\n return {\n validateConnection: (ctx) => this.validateConnection(ctx),\n createClient: (ctx) => this.createClient(ctx),\n getConnectionSettingsBadges: (ctx) =>\n resolveServiceM8ConnectionSettingsBadges(ctx, this.formatService, this.settingsService),\n };\n }\n\n private async validateConnection(ctx: AXPIntegrationRuntimeContext): Promise<AXPIntegrationValidationResult> {\n if (!this.hasClientCredentials(ctx)) {\n return {\n valid: false,\n status: AXP_INTEGRATION_CONNECTION_STATUS.Invalid,\n errorMessage: 'ServiceM8 App ID and App Secret are required.',\n };\n }\n\n return {\n valid: true,\n status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n externalAccountName: trim(defaultTo(ctx.instanceUrl, 'ServiceM8')) || 'ServiceM8',\n };\n }\n\n private async createClient(ctx: AXPIntegrationRuntimeContext): Promise<{ clientId: string; baseUrl?: string }> {\n const credentials = await this.resolveClientCredentials(ctx);\n return {\n clientId: credentials.clientId,\n baseUrl: defaultTo(ctx.instanceUrl, undefined),\n };\n }\n\n private hasClientCredentials(ctx: AXPIntegrationRuntimeContext): boolean {\n const config = (ctx.config ?? {}) as AXEServiceM8ConnectionConfig;\n const clientId = trim(defaultTo(config.clientId, ''));\n const clientSecret = trim(defaultTo(config.clientSecret, ''));\n const legacyToken = trim(defaultTo(config.accessToken, ''));\n const refreshToken = trim(defaultTo(config.refreshToken, ''));\n return Boolean((clientId && clientSecret) || legacyToken || refreshToken);\n }\n\n private async resolveClientCredentials(\n ctx: AXPIntegrationRuntimeContext,\n ): Promise<{ clientId: string; clientSecret?: string }> {\n const config = (ctx.config ?? {}) as AXEServiceM8ConnectionConfig;\n const configClientId = trim(defaultTo(config.clientId, ''));\n const configClientSecret = trim(defaultTo(config.clientSecret, ''));\n\n if (configClientId && configClientSecret) {\n return { clientId: configClientId, clientSecret: configClientSecret };\n }\n\n if (!this.secretStore || !trim(defaultTo(ctx.secretRef, ''))) {\n throw new Error('ServiceM8 connection has no client credentials.');\n }\n\n const credentials = await this.secretStore.resolve(ctx.secretRef, ctx);\n const clientId = trim(defaultTo(credentials.token ?? credentials.email, ''));\n const clientSecret = trim(defaultTo(credentials.password ?? credentials.apiToken, ''));\n if (!clientId || !clientSecret) {\n throw new Error('ServiceM8 connection has no usable client credentials.');\n }\n\n return { clientId, clientSecret };\n }\n}\n\nexport const provideServiceM8IntegrationRuntimeProvider = {\n provide: AXP_INTEGRATION_RUNTIME_PROVIDER,\n useClass: AXEServiceM8IntegrationRuntimeProvider,\n multi: true,\n};\n","import {\n AXP_LOGO_PROVIDER,\n type AXPLogoProvider,\n type AXPLogoRequest,\n type AXPLogoView,\n} from '@acorex-platform/framework-client/core';\nimport {\n AXE_SERVICEM8_MARK_ASPECT,\n AXE_SERVICEM8_MARK_SRC,\n axpServiceM8LogoKey,\n} from './servicem8-logo-key';\n\nconst servicem8LogoProvider: AXPLogoProvider = {\n key: axpServiceM8LogoKey,\n resolve: async (request: AXPLogoRequest): Promise<AXPLogoView> => ({\n kind: 'image',\n src: AXE_SERVICEM8_MARK_SRC,\n height: request.size,\n width: Math.round(request.size * AXE_SERVICEM8_MARK_ASPECT),\n }),\n};\n\nexport const AXE_SERVICEM8_LOGO_PROVIDER = {\n provide: AXP_LOGO_PROVIDER,\n useValue: servicem8LogoProvider,\n multi: true,\n} as const;\n","//#region ---- Manifest ----\n\nimport { AXPModuleManifest } from '@acorex-platform/framework-client/core';\nimport { RootConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\nexport const ServiceM8ExtensionManifest: AXPModuleManifest = {\n name: RootConfig.module.name,\n version: '1.0.0',\n title: RootConfig.module.title,\n icon: RootConfig.module.icon,\n i18n: RootConfig.config.i18n,\n type: 'integration',\n domain: 'project-management',\n dependencies: [],\n};\n\n//#endregion\n","//#region ---- Imports ----\n\nimport {\n AXPCommonMenuKeys\n} from '@acorex-platform/module-common-client/contracts';\nimport { AXPMenuProvider, AXPMenuProviderContext } from '@acorex-platform/framework-client/common';\nimport { Injectable } from '@angular/core';\nimport {\n AXEServiceM8MenuKeys,\n RootConfig,\n AXPAdministrationPermissionKeys\n} from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\n//#endregion\n\n@Injectable()\nexport class AXEServiceM8MenuProvider implements AXPMenuProvider {\n async provide(context: AXPMenuProviderContext): Promise<void> {\n const module = RootConfig.module;\n const policy = {\n features: [module.name],\n permissions: [AXPAdministrationPermissionKeys.MaintainConnections],\n };\n\n const configMenu = context.find(AXPCommonMenuKeys.Configuration);\n if (!context.find(AXEServiceM8MenuKeys.ServiceM8ExtensionConfig).exists) {\n configMenu.addItems([\n {\n name: AXEServiceM8MenuKeys.ServiceM8ExtensionConfig,\n text: '@extensions-servicem8:module.menus.configuration.title',\n icon: module.icon,\n type: 'menu',\n priority: 8940,\n policy,\n children: [],\n },\n ]);\n }\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXMIntegrationManagementModule } from '@acorex-platform/module-integration-management-client';\nimport { AXP_INTEGRATION_PROVIDER, AXP_MENU_PROVIDER } from '@acorex-platform/framework-client/common';\nimport { AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER } from '@acorex-platform/framework-client/core';\nimport { AXP_ENTITY_MODIFIER } from '@acorex-platform/framework-client/layout/entity';\nimport { provideCommandSetups } from '@acorex-platform/framework-client/runtime';\nimport { NgModule } from '@angular/core';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider } from './features/project-management/servicem8-project-link-expression-evaluator-scope.provider';\nimport { AXEServiceM8ProjectEntityModifier } from './features/project-management/project-servicem8.entity-modifier';\nimport { AXEServiceM8IntegrationProvider } from './integration/servicem8.integration.provider';\nimport { provideServiceM8IntegrationRuntimeProvider } from './integration/servicem8.integration-runtime.provider';\nimport { AXE_SERVICEM8_LOGO_PROVIDER } from './brand/servicem8-logo.provider';\nimport { ServiceM8ExtensionManifest } from './manifest';\nimport { AXEServiceM8MenuProvider } from './menu.provider';\n\n//#endregion\n\n@NgModule({\n imports: [AXMIntegrationManagementModule],\n providers: [\n AXE_SERVICEM8_LOGO_PROVIDER,\n { provide: AXP_MODULE_MANIFEST_PROVIDER, useValue: ServiceM8ExtensionManifest, multi: true },\n { provide: AXP_MENU_PROVIDER, useClass: AXEServiceM8MenuProvider, multi: true },\n { provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8ProjectEntityModifier, multi: true },\n {\n provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,\n useClass: AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider,\n multi: true,\n },\n { provide: AXP_INTEGRATION_PROVIDER, useClass: AXEServiceM8IntegrationProvider, multi: true },\n provideServiceM8IntegrationRuntimeProvider,\n provideCommandSetups([\n {\n key: AXEServiceM8CommandKeys.ConnectionConnect,\n command: () => import('./features/connect/connect-servicem8.command').then((c) => c.ConnectServiceM8Command),\n },\n {\n key: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,\n command: () =>\n import('./features/connect/complete-servicem8-oauth.command').then((c) => c.CompleteServiceM8OAuthCommand),\n },\n ]),\n ],\n})\nexport class AXEServiceM8ExtensionModule {}\n\n//#endregion\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["PmRootConfig","RootConfig"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client.mjs","sources":["../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/servicem8-expression-scope.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/servicem8-project-link-expression-evaluator-scope.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/project-management/project-servicem8.entity-modifier.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/customer-management/customer-servicem8.entity-modifier.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/brand/servicem8-logo-key.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8.integration.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8-integration-settings-badges.util.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8.integration-runtime.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/integration/servicem8.connection-lifecycle.handler.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/brand/servicem8-logo.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/manifest.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/menu.provider.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/servicem8-extension.module.ts","../../../../libs/extensions/project-management/servicem8/client/src/acorex-platform-extension-project-management-servicem8-client.ts"],"sourcesContent":["export const AXE_SERVICEM8_EXPRESSION_SCOPE = 'ServiceM8Extension';\n","//#region ---- Imports ----\n\nimport { AXPExpressionEvaluatorScopeProvider, AXPExpressionEvaluatorScopeProviderContext } from '@acorex-platform/framework-shared/core';\nimport { AXPIntegrationRuntimeService } from '@acorex-platform/framework-client/common';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { inject } from '@angular/core';\nimport { AXE_PM_INTEGRATION_PROVIDER_SERVICEM8 } from '@acorex-platform/extension-project-management-core-client/contracts';\nimport { RootConfig as PmRootConfig } from '@acorex-platform/module-project-management-client/contracts';\nimport type { AXMProjectManagementProjectEntityModel } from '@acorex-platform/module-project-management-client/contracts';\nimport { AXE_SERVICEM8_EXPRESSION_SCOPE } from './servicem8-expression-scope';\n\n//#endregion\n\nexport class AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider implements AXPExpressionEvaluatorScopeProvider {\n private readonly entityService = inject(AXPEntityService);\n private readonly integrationRuntime = inject(AXPIntegrationRuntimeService);\n\n async provide(context: AXPExpressionEvaluatorScopeProviderContext): Promise<void> {\n context.addScope(AXE_SERVICEM8_EXPRESSION_SCOPE, {\n hasProjectLink: async (platformProjectIdRaw?: unknown): Promise<boolean> => {\n const platformProjectId = typeof platformProjectIdRaw === 'string' ? platformProjectIdRaw.trim() : '';\n if (!platformProjectId) {\n return false;\n }\n\n const project = (await this.entityService\n .withEntity(PmRootConfig.module.name, PmRootConfig.entities.project.name)\n .data<string, AXMProjectManagementProjectEntityModel>()\n .byKey(platformProjectId)) as AXMProjectManagementProjectEntityModel | null;\n\n return project?.integrationRef?.source === AXE_PM_INTEGRATION_PROVIDER_SERVICEM8;\n },\n hasServiceM8Connection: async (): Promise<boolean> => {\n try {\n await this.integrationRuntime.getConnection({ providerId: 'servicem8', connectionScope: 'tenant' });\n return true;\n } catch {\n return false;\n }\n },\n });\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXPSystemActionType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityAction, AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';\nimport {\n actionExists,\n AXPEntityModifierProvider,\n ensureListActions,\n} from '@acorex-platform/framework-client/layout/entity';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { RootConfig as PmRootConfig } from '@acorex-platform/module-project-management-client/contracts';\nimport { AXE_SERVICEM8_EXPRESSION_SCOPE } from './servicem8-expression-scope';\n\n//#endregion\n\nconst IMPORT_ORDER = 36;\nconst SYNC_ORDER = 37;\n\nfunction buildImportAction(): AXPEntityAction {\n return {\n name: AXEServiceM8CommandKeys.ProjectImportFromServiceM8,\n title: '@extensions-servicem8:actions.import-from-servicem8.title',\n command: { name: AXEServiceM8CommandKeys.ProjectImportFromServiceM8 },\n priority: 'secondary',\n type: AXPSystemActionType.Import,\n icon: 'fa-light fa-briefcase',\n scope: AXPEntityCommandScope.TypeLevel,\n order: IMPORT_ORDER,\n };\n}\n\nfunction buildSyncAction(): AXPEntityAction {\n return {\n name: AXEServiceM8CommandKeys.ProjectSync,\n title: '@extensions-servicem8:actions.sync.title',\n command: {\n name: AXEServiceM8CommandKeys.ProjectSync,\n options: { platformProjectId: '{{ context.eval(\"id\") }}' },\n },\n priority: 'secondary',\n type: AXPSystemActionType.Sync,\n icon: 'fa-light fa-arrows-rotate',\n scope: AXPEntityCommandScope.Individual,\n order: SYNC_ORDER,\n hidden: `{{ !(await ${AXE_SERVICEM8_EXPRESSION_SCOPE}.hasProjectLink(context.eval(\"id\"))) }}`,\n };\n}\n\n/** Adds ServiceM8 import/sync actions to ProjectManagement.Project views. */\nexport const AXEServiceM8ProjectEntityModifier: AXPEntityModifierProvider = {\n entityName: PmRootConfig.entities.project.name,\n order: 50,\n modifier: (ctx) => {\n if (ctx.module.get() !== PmRootConfig.module.name) {\n return;\n }\n\n ensureListActions(ctx);\n\n ctx.interfaces.update((interfaces) => {\n const next = (interfaces ?? {}) as Record<string, unknown>;\n const master = (next['master'] ?? {}) as Record<string, unknown>;\n const list = (master['list'] ?? { actions: [], views: [] }) as Record<string, unknown>;\n const listActions = (list['actions'] ?? []) as AXPEntityAction[];\n\n if (!actionExists(listActions, AXEServiceM8CommandKeys.ProjectImportFromServiceM8)) {\n listActions.push(buildImportAction());\n }\n list['actions'] = listActions;\n master['list'] = list;\n\n const single = master['single'] as Record<string, unknown> | undefined;\n if (single) {\n const singleActions = (single['actions'] ?? []) as AXPEntityAction[];\n if (!actionExists(singleActions, AXEServiceM8CommandKeys.ProjectSync)) {\n singleActions.push(buildSyncAction());\n }\n single['actions'] = singleActions;\n }\n\n next['master'] = master;\n return next as typeof interfaces;\n });\n },\n};\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXPSystemActionType } from '@acorex-platform/framework-shared/core';\nimport { AXPEntityAction, AXPEntityCommandScope } from '@acorex-platform/framework-shared/entity';\nimport {\n actionExists,\n AXPEntityModifierProvider,\n ensureListActions,\n} from '@acorex-platform/framework-client/layout/entity';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { RootConfig as CustomerRootConfig } from '@acorex-platform/module-customer-management-client/contracts';\n\n//#endregion\n\n//#region ----- Constants -----\n\nconst IMPORT_ORDER = 36;\n\n//#endregion\n\n//#region ----- Actions -----\n\nfunction buildImportAction(): AXPEntityAction {\n return {\n name: AXEServiceM8CommandKeys.CustomerImportFromServiceM8,\n title: '@extensions-servicem8:actions.import-from-servicem8.title',\n command: { name: AXEServiceM8CommandKeys.CustomerImportFromServiceM8 },\n priority: 'secondary',\n type: AXPSystemActionType.Import,\n icon: 'fa-light fa-briefcase',\n scope: AXPEntityCommandScope.TypeLevel,\n order: IMPORT_ORDER,\n };\n}\n\n//#endregion\n\n//#region ----- Modifier -----\n\n/** Adds ServiceM8 import action to CustomerManagement.Customer list views. */\nexport const AXEServiceM8CustomerEntityModifier: AXPEntityModifierProvider = {\n entityName: CustomerRootConfig.entities.customer.name,\n order: 50,\n modifier: (ctx) => {\n if (ctx.module.get() !== CustomerRootConfig.module.name) {\n return;\n }\n\n ensureListActions(ctx);\n\n ctx.interfaces.master.list.update((list) => {\n const next = list ?? { actions: [], views: [] };\n const listActions = [...(next.actions ?? [])];\n if (!actionExists(listActions, AXEServiceM8CommandKeys.CustomerImportFromServiceM8)) {\n listActions.push(buildImportAction());\n }\n return {\n ...next,\n actions: listActions,\n };\n });\n },\n};\n\n//#endregion\n","//#region ---- ServiceM8 logo registry key ----\n\nexport const axpServiceM8LogoKey = 'servicem8' as const;\n\n/** Mark artwork (1024×1024); consuming apps copy to `assets/images/brand/integrations/`. */\nexport const AXE_SERVICEM8_MARK_SRC = 'assets/images/brand/integrations/servicem8-mark.png';\n\n/** Source mark is square. */\nexport const AXE_SERVICEM8_MARK_ASPECT = 1;\n\n//#endregion\n","import {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n AXP_INTEGRATION_CAPABILITY,\n AXP_INTEGRATION_CONNECTION_SCOPE,\n AXPWidgetsList,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPIntegrationProvider, AXPIntegrationProviderContext } from '@acorex-platform/framework-client/common';\nimport { Injectable } from '@angular/core';\nimport { AXEServiceM8CommandKeys, RootConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { axpServiceM8LogoKey } from '../brand/servicem8-logo-key';\n\n@Injectable()\nexport class AXEServiceM8IntegrationProvider implements AXPIntegrationProvider {\n async provide(context: AXPIntegrationProviderContext): Promise<void> {\n const I18N = `@${RootConfig.config.i18n}:integration`;\n\n context.register({\n domainId: 'project-management',\n id: 'servicem8',\n module: RootConfig.module.name,\n displayName: `${I18N}.display-name`,\n description: `${I18N}.description`,\n icon: RootConfig.module.icon,\n logoKey: axpServiceM8LogoKey,\n capabilities: [AXP_INTEGRATION_CAPABILITY.Sync, AXP_INTEGRATION_CAPABILITY.Import],\n connectionScopes: [AXP_INTEGRATION_CONNECTION_SCOPE.Tenant],\n allowMultipleConnections: true,\n defaultConnectionKey: 'default',\n connectCommandKey: AXEServiceM8CommandKeys.ConnectionConnect,\n completeOAuthCommandKey: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,\n authMethods: [\n {\n type: AXP_INTEGRATION_AUTH_METHOD_TYPE.OAuth2,\n label: `${I18N}.auth.oauth.label`,\n instructions: `${I18N}.auth.oauth.instructions`,\n usesRedirect: false,\n supportsRefresh: true,\n supportsRevoke: false,\n supportsValidation: true,\n fields: [\n {\n type: AXPWidgetsList.Editors.TextBox,\n path: 'clientId',\n options: { placeholder: `${I18N}.auth.oauth.client-id.placeholder` },\n },\n {\n type: AXPWidgetsList.Editors.PasswordBox,\n path: 'clientSecret',\n options: { placeholder: `${I18N}.auth.oauth.client-secret.placeholder` },\n },\n ],\n },\n ],\n });\n }\n}\n","//#region ---- ServiceM8 integration settings badges ----\n\nimport { AXFormatService } from '@acorex/core/format';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';\nimport type {\n AXPIntegrationConnectionSettingsContext,\n AXPIntegrationSettingsRowBadge,\n} from '@acorex-platform/framework-shared/core';\nimport type { AXPBackgroundJobSchedule } from '@acorex-platform/framework-shared/background-job';\nimport type { AXEServiceM8ConnectionConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\nconst SERVICEM8_I18N = '@extensions-servicem8:integration.badges';\n\n/** Must match `SERVICEM8_PULL_JOBS_COMMAND_KEY` / schedule `command.key`. */\nexport const SERVICEM8_PULL_JOBS_SCHEDULE_COMMAND_KEY = 'servicem8-extension.jobs.pull';\n\nasync function formatSyncTimestamp(\n iso: string,\n formatService: AXFormatService,\n settingsService: AXPSettingsService,\n): Promise<string | undefined> {\n const parsed = Date.parse(iso);\n if (!Number.isFinite(parsed)) {\n return undefined;\n }\n\n const dateFormat = await settingsService.get(AXPRegionalSetting.ShortDate);\n const timeFormat = await settingsService.get(AXPRegionalSetting.ShortTime);\n const format = `${dateFormat} ${timeFormat}`.trim();\n\n return formatService.format(new Date(parsed), 'datetime', { format });\n}\n\nfunction isFailureNewer(schedule: AXPBackgroundJobSchedule): boolean {\n const failed = schedule.lastFailureAt ? Date.parse(schedule.lastFailureAt) : NaN;\n const succeeded = schedule.lastSuccessAt ? Date.parse(schedule.lastSuccessAt) : NaN;\n if (!Number.isFinite(failed)) {\n return false;\n }\n if (!Number.isFinite(succeeded)) {\n return true;\n }\n return failed >= succeeded;\n}\n\nexport async function resolveServiceM8ConnectionSettingsBadges(\n ctx: AXPIntegrationConnectionSettingsContext,\n formatService: AXFormatService,\n settingsService: AXPSettingsService,\n schedule?: AXPBackgroundJobSchedule | null,\n): Promise<AXPIntegrationSettingsRowBadge[]> {\n const config = (ctx.connection.config ?? {}) as AXEServiceM8ConnectionConfig;\n const jobsSync = config.jobsSync as Record<string, unknown> | undefined;\n const lastSync =\n config.jobsSync?.lastSyncAt?.trim() ||\n (typeof jobsSync?.['lastSuccessfulSyncAt'] === 'string' ? jobsSync['lastSuccessfulSyncAt'].trim() : '');\n\n const badges: AXPIntegrationSettingsRowBadge[] = [];\n\n if (!lastSync) {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.never-synced`,\n color: 'warning',\n });\n } else {\n const datetime = await formatSyncTimestamp(lastSync, formatService, settingsService);\n if (datetime) {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.last-sync`,\n params: { datetime },\n color: 'success',\n });\n }\n }\n\n if (!schedule) {\n return badges;\n }\n\n if (schedule.status === 'pause') {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.schedule-paused`,\n color: 'warning',\n });\n } else if (schedule.status === 'disabled') {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.schedule-disabled`,\n color: 'warning',\n });\n }\n\n if (schedule.nextRunAt) {\n const datetime = await formatSyncTimestamp(schedule.nextRunAt, formatService, settingsService);\n if (datetime) {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.next-run`,\n params: { datetime },\n color: 'secondary',\n });\n }\n }\n\n if (isFailureNewer(schedule) && schedule.lastFailureAt) {\n const datetime = await formatSyncTimestamp(schedule.lastFailureAt, formatService, settingsService);\n if (datetime) {\n badges.push({\n labelKey: `${SERVICEM8_I18N}.last-failure`,\n params: { datetime },\n color: 'danger',\n });\n }\n }\n\n return badges;\n}\n\n//#endregion\n","import {\n AXP_INTEGRATION_CONNECTION_STATUS,\n runtimeQueryPayloadData,\n type AXPIntegrationProviderRuntimeHooks,\n type AXPIntegrationRuntimeContext,\n type AXPIntegrationValidationResult,\n} from '@acorex-platform/framework-shared/core';\nimport {\n AXP_INTEGRATION_RUNTIME_PROVIDER,\n AXP_INTEGRATION_SECRET_STORE,\n type AXPIntegrationRuntimeProvider,\n} from '@acorex-platform/framework-client/common';\nimport type { AXEServiceM8ConnectionConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { Injectable, inject } from '@angular/core';\nimport { AXFormatService } from '@acorex/core/format';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { defaultTo, trim } from 'lodash-es';\nimport { AXPQueryService } from '@acorex-platform/framework-client/runtime';\nimport {\n AXPBackgroundJobQueryKeys,\n type AXPBackgroundJobSchedule,\n} from '@acorex-platform/framework-shared/background-job';\nimport {\n resolveServiceM8ConnectionSettingsBadges,\n SERVICEM8_PULL_JOBS_SCHEDULE_COMMAND_KEY,\n} from './servicem8-integration-settings-badges.util';\n\n@Injectable()\nexport class AXEServiceM8IntegrationRuntimeProvider implements AXPIntegrationRuntimeProvider {\n readonly providerId = 'servicem8';\n\n private readonly secretStore = inject(AXP_INTEGRATION_SECRET_STORE, { optional: true });\n private readonly formatService = inject(AXFormatService);\n private readonly settingsService = inject(AXPSettingsService);\n private readonly queryService = inject(AXPQueryService, { optional: true });\n\n async getHooks(): Promise<AXPIntegrationProviderRuntimeHooks> {\n return {\n validateConnection: (ctx) => this.validateConnection(ctx),\n createClient: (ctx) => this.createClient(ctx),\n getConnectionSettingsBadges: async (ctx) =>\n resolveServiceM8ConnectionSettingsBadges(\n ctx,\n this.formatService,\n this.settingsService,\n await this.loadPullSchedule(ctx.connection.id),\n ),\n };\n }\n\n private async validateConnection(ctx: AXPIntegrationRuntimeContext): Promise<AXPIntegrationValidationResult> {\n if (!this.hasClientCredentials(ctx)) {\n return {\n valid: false,\n status: AXP_INTEGRATION_CONNECTION_STATUS.Invalid,\n errorMessage: 'ServiceM8 App ID and App Secret are required.',\n };\n }\n\n return {\n valid: true,\n status: AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n externalAccountName: trim(defaultTo(ctx.instanceUrl, 'ServiceM8')) || 'ServiceM8',\n };\n }\n\n private async createClient(ctx: AXPIntegrationRuntimeContext): Promise<{ clientId: string; baseUrl?: string }> {\n const credentials = await this.resolveClientCredentials(ctx);\n return {\n clientId: credentials.clientId,\n baseUrl: defaultTo(ctx.instanceUrl, undefined),\n };\n }\n\n private hasClientCredentials(ctx: AXPIntegrationRuntimeContext): boolean {\n const config = (ctx.config ?? {}) as AXEServiceM8ConnectionConfig;\n const clientId = trim(defaultTo(config.clientId, ''));\n const clientSecret = trim(defaultTo(config.clientSecret, ''));\n const legacyToken = trim(defaultTo(config.accessToken, ''));\n const refreshToken = trim(defaultTo(config.refreshToken, ''));\n return Boolean((clientId && clientSecret) || legacyToken || refreshToken);\n }\n\n private async resolveClientCredentials(\n ctx: AXPIntegrationRuntimeContext,\n ): Promise<{ clientId: string; clientSecret?: string }> {\n const config = (ctx.config ?? {}) as AXEServiceM8ConnectionConfig;\n const configClientId = trim(defaultTo(config.clientId, ''));\n const configClientSecret = trim(defaultTo(config.clientSecret, ''));\n\n if (configClientId && configClientSecret) {\n return { clientId: configClientId, clientSecret: configClientSecret };\n }\n\n if (!this.secretStore || !trim(defaultTo(ctx.secretRef, ''))) {\n throw new Error('ServiceM8 connection has no client credentials.');\n }\n\n const credentials = await this.secretStore.resolve(ctx.secretRef, ctx);\n const clientId = trim(defaultTo(credentials.token ?? credentials.email, ''));\n const clientSecret = trim(defaultTo(credentials.password ?? credentials.apiToken, ''));\n if (!clientId || !clientSecret) {\n throw new Error('ServiceM8 connection has no usable client credentials.');\n }\n\n return { clientId, clientSecret };\n }\n\n private async loadPullSchedule(connectionId: string): Promise<AXPBackgroundJobSchedule | null> {\n if (!this.queryService || !connectionId.trim()) {\n return null;\n }\n try {\n const result = await this.queryService.fetch<\n { commandKey: string; connectionId?: string },\n AXPBackgroundJobSchedule | null\n >(AXPBackgroundJobQueryKeys.ScheduleGetByScope, {\n commandKey: SERVICEM8_PULL_JOBS_SCHEDULE_COMMAND_KEY,\n connectionId,\n });\n return runtimeQueryPayloadData(result) ?? null;\n } catch {\n return null;\n }\n }\n}\n\nexport const provideServiceM8IntegrationRuntimeProvider = {\n provide: AXP_INTEGRATION_RUNTIME_PROVIDER,\n useClass: AXEServiceM8IntegrationRuntimeProvider,\n multi: true,\n};\n","//#region ---- Imports ----\n\nimport {\n AXP_INTEGRATION_CONNECTION_LIFECYCLE,\n type AXPIntegrationConnectionLifecycleHandler,\n} from '@acorex-platform/framework-client/common';\nimport { AXP_INTEGRATION_CONNECTION_STATUS, type AXPSafeIntegrationConnectionDto } from '@acorex-platform/framework-shared/core';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { Injectable, inject } from '@angular/core';\n\n//#endregion\n\n//#region ---- Handler ----\n\n@Injectable()\nexport class AXEServiceM8ConnectionLifecycleHandler implements AXPIntegrationConnectionLifecycleHandler {\n readonly providerId = 'servicem8';\n\n private readonly commandService = inject(AXPCommandService);\n\n async onDisconnected(connection: AXPSafeIntegrationConnectionDto): Promise<void> {\n await this.runLifecycle(connection.id, 'disconnected');\n }\n\n async onDeleted(connection: AXPSafeIntegrationConnectionDto): Promise<void> {\n await this.runLifecycle(connection.id, 'deleted');\n }\n\n async onEnabledChanged(connection: AXPSafeIntegrationConnectionDto, enabled: boolean): Promise<void> {\n if (enabled) {\n if (connection.status === AXP_INTEGRATION_CONNECTION_STATUS.Connected) {\n await this.runLifecycle(connection.id, 'enabled');\n }\n return;\n }\n await this.runLifecycle(connection.id, 'disabled');\n }\n\n private async runLifecycle(\n connectionId: string,\n action: 'connected' | 'disconnected' | 'deleted' | 'enabled' | 'disabled',\n ): Promise<void> {\n await this.commandService.execute(AXEServiceM8CommandKeys.ConnectionLifecycle, {\n connectionId,\n action,\n });\n }\n}\n\nexport const provideServiceM8ConnectionLifecycleHandler = {\n provide: AXP_INTEGRATION_CONNECTION_LIFECYCLE,\n useClass: AXEServiceM8ConnectionLifecycleHandler,\n multi: true,\n};\n\n//#endregion\n","import {\n AXP_LOGO_PROVIDER,\n type AXPLogoProvider,\n type AXPLogoRequest,\n type AXPLogoView,\n} from '@acorex-platform/framework-client/core';\nimport {\n AXE_SERVICEM8_MARK_ASPECT,\n AXE_SERVICEM8_MARK_SRC,\n axpServiceM8LogoKey,\n} from './servicem8-logo-key';\n\nconst servicem8LogoProvider: AXPLogoProvider = {\n key: axpServiceM8LogoKey,\n resolve: async (request: AXPLogoRequest): Promise<AXPLogoView> => ({\n kind: 'image',\n src: AXE_SERVICEM8_MARK_SRC,\n height: request.size,\n width: Math.round(request.size * AXE_SERVICEM8_MARK_ASPECT),\n }),\n};\n\nexport const AXE_SERVICEM8_LOGO_PROVIDER = {\n provide: AXP_LOGO_PROVIDER,\n useValue: servicem8LogoProvider,\n multi: true,\n} as const;\n","//#region ---- Manifest ----\n\nimport { AXPModuleManifest } from '@acorex-platform/framework-client/core';\nimport { RootConfig } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\nexport const ServiceM8ExtensionManifest: AXPModuleManifest = {\n name: RootConfig.module.name,\n version: '1.0.0',\n title: RootConfig.module.title,\n icon: RootConfig.module.icon,\n i18n: RootConfig.config.i18n,\n type: 'integration',\n domain: 'project-management',\n dependencies: [],\n};\n\n//#endregion\n","//#region ---- Imports ----\n\nimport {\n AXPCommonMenuKeys\n} from '@acorex-platform/module-common-client/contracts';\nimport { AXPMenuProvider, AXPMenuProviderContext } from '@acorex-platform/framework-client/common';\nimport { Injectable } from '@angular/core';\nimport {\n AXEServiceM8MenuKeys,\n RootConfig,\n AXPAdministrationPermissionKeys\n} from '@acorex-platform/extension-project-management-servicem8-client/contracts';\n\n//#endregion\n\n@Injectable()\nexport class AXEServiceM8MenuProvider implements AXPMenuProvider {\n async provide(context: AXPMenuProviderContext): Promise<void> {\n const module = RootConfig.module;\n const policy = {\n features: [module.name],\n permissions: [AXPAdministrationPermissionKeys.MaintainConnections],\n };\n\n const configMenu = context.find(AXPCommonMenuKeys.Configuration);\n if (!context.find(AXEServiceM8MenuKeys.ServiceM8ExtensionConfig).exists) {\n configMenu.addItems([\n {\n name: AXEServiceM8MenuKeys.ServiceM8ExtensionConfig,\n text: '@extensions-servicem8:module.menus.configuration.title',\n icon: module.icon,\n type: 'menu',\n priority: 8940,\n policy,\n children: [],\n },\n ]);\n }\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXMIntegrationManagementModule } from '@acorex-platform/module-integration-management-client';\nimport { AXP_INTEGRATION_PROVIDER, AXP_MENU_PROVIDER } from '@acorex-platform/framework-client/common';\nimport { AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER } from '@acorex-platform/framework-client/core';\nimport { AXP_ENTITY_MODIFIER } from '@acorex-platform/framework-client/layout/entity';\nimport { provideCommandSetups } from '@acorex-platform/framework-client/runtime';\nimport { NgModule } from '@angular/core';\nimport { AXEServiceM8CommandKeys } from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport { AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider } from './features/project-management/servicem8-project-link-expression-evaluator-scope.provider';\nimport { AXEServiceM8ProjectEntityModifier } from './features/project-management/project-servicem8.entity-modifier';\nimport { AXEServiceM8CustomerEntityModifier } from './features/customer-management/customer-servicem8.entity-modifier';\nimport { AXEServiceM8IntegrationProvider } from './integration/servicem8.integration.provider';\nimport { provideServiceM8IntegrationRuntimeProvider } from './integration/servicem8.integration-runtime.provider';\nimport { provideServiceM8ConnectionLifecycleHandler } from './integration/servicem8.connection-lifecycle.handler';\nimport { AXE_SERVICEM8_LOGO_PROVIDER } from './brand/servicem8-logo.provider';\nimport { ServiceM8ExtensionManifest } from './manifest';\nimport { AXEServiceM8MenuProvider } from './menu.provider';\n\n//#endregion\n\n@NgModule({\n imports: [AXMIntegrationManagementModule],\n providers: [\n AXE_SERVICEM8_LOGO_PROVIDER,\n { provide: AXP_MODULE_MANIFEST_PROVIDER, useValue: ServiceM8ExtensionManifest, multi: true },\n { provide: AXP_MENU_PROVIDER, useClass: AXEServiceM8MenuProvider, multi: true },\n { provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8ProjectEntityModifier, multi: true },\n { provide: AXP_ENTITY_MODIFIER, useValue: AXEServiceM8CustomerEntityModifier, multi: true },\n {\n provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,\n useClass: AXEServiceM8ProjectLinkExpressionEvaluatorScopeProvider,\n multi: true,\n },\n { provide: AXP_INTEGRATION_PROVIDER, useClass: AXEServiceM8IntegrationProvider, multi: true },\n provideServiceM8IntegrationRuntimeProvider,\n provideServiceM8ConnectionLifecycleHandler,\n provideCommandSetups([\n {\n key: AXEServiceM8CommandKeys.ConnectionConnect,\n command: () => import('./features/connect/connect-servicem8.command').then((c) => c.ConnectServiceM8Command),\n },\n {\n key: AXEServiceM8CommandKeys.ConnectionCompleteOAuth,\n command: () =>\n import('./features/connect/complete-servicem8-oauth.command').then((c) => c.CompleteServiceM8OAuthCommand),\n },\n ]),\n ],\n})\nexport class AXEServiceM8ExtensionModule {}\n\n//#endregion\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["PmRootConfig","IMPORT_ORDER","buildImportAction","AXEServiceM8CommandKeys","CustomerRootConfig","RootConfig"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acorex-platform/extension-project-management-servicem8-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.33",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@acorex-platform/extension-project-management-core-client": "0.0.
|
|
6
|
+
"@acorex-platform/extension-project-management-core-client": "0.0.33",
|
|
7
7
|
"@angular/common": "^21.0.0 || ^22.0.0",
|
|
8
8
|
"@angular/core": "^21.0.0 || ^22.0.0"
|
|
9
9
|
},
|
|
@@ -15,10 +15,12 @@ declare const RootConfig: {
|
|
|
15
15
|
declare const AXEServiceM8CommandKeys: {
|
|
16
16
|
readonly ConnectionConnect: "servicem8-extension.Connection:Connect";
|
|
17
17
|
readonly ConnectionCompleteOAuth: "servicem8-extension.Connection:CompleteOAuth";
|
|
18
|
+
readonly ConnectionLifecycle: "servicem8-extension.Connection:Lifecycle";
|
|
18
19
|
readonly OAuthStart: "servicem8-extension.OAuth:Start";
|
|
19
20
|
readonly OAuthComplete: "servicem8-extension.OAuth:Complete";
|
|
20
21
|
readonly OAuthValidate: "servicem8-extension.OAuth:Validate";
|
|
21
22
|
readonly ProjectImportFromServiceM8: "servicem8-extension.Project:ImportFromServiceM8";
|
|
23
|
+
readonly CustomerImportFromServiceM8: "servicem8-extension.Customer:ImportFromServiceM8";
|
|
22
24
|
readonly ProjectSync: "servicem8-extension.Project:Sync";
|
|
23
25
|
readonly JobsPull: "servicem8-extension.Jobs:Pull";
|
|
24
26
|
readonly JobsRefresh: "servicem8-extension.Jobs:Refresh";
|
|
@@ -66,6 +68,9 @@ declare const AXEServiceM8Permissions: {
|
|
|
66
68
|
readonly ProjectImport: {
|
|
67
69
|
readonly Execute: "Administration:Permission:ManageIntegrationActions";
|
|
68
70
|
};
|
|
71
|
+
readonly CustomerImport: {
|
|
72
|
+
readonly Execute: "Administration:Permission:ManageIntegrationActions";
|
|
73
|
+
};
|
|
69
74
|
readonly ProjectSync: {
|
|
70
75
|
readonly Execute: "Administration:Permission:ManageIntegrationActions";
|
|
71
76
|
};
|
|
@@ -138,7 +143,44 @@ interface AXEServiceM8RemoteJob {
|
|
|
138
143
|
billing_address?: string | null;
|
|
139
144
|
work_done_description?: string | null;
|
|
140
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* ServiceM8 company (client) — cached as `resourceType=customer`.
|
|
148
|
+
* Includes ServiceM8 address fields plus optional Simpro-shaped aliases when present.
|
|
149
|
+
*/
|
|
150
|
+
interface AXEServiceM8RemoteCustomer {
|
|
151
|
+
uuid: string;
|
|
152
|
+
name?: string | null;
|
|
153
|
+
address?: string | null;
|
|
154
|
+
address_street?: string | null;
|
|
155
|
+
address_city?: string | null;
|
|
156
|
+
address_state?: string | null;
|
|
157
|
+
address_postcode?: string | null;
|
|
158
|
+
address_country?: string | null;
|
|
159
|
+
fax_number?: string | null;
|
|
160
|
+
FamilyName?: string | null;
|
|
161
|
+
Phone?: string | null;
|
|
162
|
+
Email?: string | null;
|
|
163
|
+
EIN?: string | null;
|
|
164
|
+
CompanyName?: string | null;
|
|
165
|
+
active?: number | boolean | null;
|
|
166
|
+
edit_date?: string | null;
|
|
167
|
+
}
|
|
168
|
+
/** ServiceM8 companycontact — cached as `resourceType=site`. */
|
|
169
|
+
interface AXEServiceM8RemoteSite {
|
|
170
|
+
uuid: string;
|
|
171
|
+
company_uuid?: string | null;
|
|
172
|
+
first?: string | null;
|
|
173
|
+
last?: string | null;
|
|
174
|
+
phone?: string | null;
|
|
175
|
+
mobile?: string | null;
|
|
176
|
+
email?: string | null;
|
|
177
|
+
type?: string | null;
|
|
178
|
+
active?: number | boolean | null;
|
|
179
|
+
edit_date?: string | null;
|
|
180
|
+
}
|
|
141
181
|
interface AXEServiceM8PullJobsRequest {
|
|
182
|
+
/** When set, pulls for this ServiceM8 connection (required for multi-connection schedules). */
|
|
183
|
+
connectionId?: string;
|
|
142
184
|
/** Maximum ServiceM8 jobs to pull into the cache (default 250, max 1000). */
|
|
143
185
|
maxJobs?: number;
|
|
144
186
|
/**
|
|
@@ -154,6 +196,21 @@ interface AXEServiceM8PullJobsResponse {
|
|
|
154
196
|
skipped?: boolean;
|
|
155
197
|
/** Whether this run used incremental or full snapshot mode. */
|
|
156
198
|
syncMode?: 'incremental' | 'full';
|
|
199
|
+
/** Per data-type upsert counts (jobs / customers / sites). */
|
|
200
|
+
byResourceType?: {
|
|
201
|
+
job?: {
|
|
202
|
+
upserted: number;
|
|
203
|
+
deactivated: number;
|
|
204
|
+
};
|
|
205
|
+
customer?: {
|
|
206
|
+
upserted: number;
|
|
207
|
+
deactivated: number;
|
|
208
|
+
};
|
|
209
|
+
site?: {
|
|
210
|
+
upserted: number;
|
|
211
|
+
deactivated: number;
|
|
212
|
+
};
|
|
213
|
+
};
|
|
157
214
|
}
|
|
158
215
|
interface AXEServiceM8ImportJobRequest {
|
|
159
216
|
remoteRecordId: string;
|
|
@@ -164,9 +221,23 @@ interface AXEServiceM8ImportJobResponse {
|
|
|
164
221
|
platformProjectId: string;
|
|
165
222
|
created: boolean;
|
|
166
223
|
}
|
|
224
|
+
interface AXEServiceM8ImportCustomerRequest {
|
|
225
|
+
remoteRecordId: string;
|
|
226
|
+
}
|
|
227
|
+
interface AXEServiceM8ImportCustomerResponse {
|
|
228
|
+
platformCustomerId: string;
|
|
229
|
+
created: boolean;
|
|
230
|
+
}
|
|
167
231
|
interface AXEServiceM8SyncPlatformProjectRequest {
|
|
168
232
|
platformProjectId: string;
|
|
169
233
|
}
|
|
234
|
+
interface AXEServiceM8ConnectionLifecycleRequest {
|
|
235
|
+
connectionId: string;
|
|
236
|
+
action: 'connected' | 'disconnected' | 'deleted' | 'enabled' | 'disabled';
|
|
237
|
+
}
|
|
238
|
+
interface AXEServiceM8ConnectionLifecycleResponse {
|
|
239
|
+
ok: true;
|
|
240
|
+
}
|
|
170
241
|
|
|
171
242
|
/** Public OAuth authorize endpoint (fixed host). */
|
|
172
243
|
declare const AXE_SERVICEM8_OAUTH_AUTHORIZE_URL = "https://go.servicem8.com/oauth/authorize";
|
|
@@ -175,10 +246,10 @@ declare const AXE_SERVICEM8_OAUTH_TOKEN_URL = "https://go.servicem8.com/oauth/ac
|
|
|
175
246
|
/** REST API base URL stored on connection `instanceUrl`. */
|
|
176
247
|
declare const AXE_SERVICEM8_API_BASE_URL = "https://api.servicem8.com";
|
|
177
248
|
/**
|
|
178
|
-
* OAuth scopes for connect.
|
|
179
|
-
*
|
|
249
|
+
* OAuth scopes for connect / authorize.
|
|
250
|
+
* Space-separated; encoded as `scope=` query value by the OAuth start flow.
|
|
180
251
|
*/
|
|
181
|
-
declare const AXE_SERVICEM8_OAUTH_SCOPES = "read_jobs
|
|
252
|
+
declare const AXE_SERVICEM8_OAUTH_SCOPES = "read_customers read_jobs read_staff read_job_contacts read_job_attachments publish_job_attachments read_customer_contacts";
|
|
182
253
|
|
|
183
254
|
export { AXEServiceM8CommandKeys, AXEServiceM8MenuKeys, AXEServiceM8Permissions, AXE_SERVICEM8_API_BASE_URL, AXE_SERVICEM8_OAUTH_AUTHORIZE_URL, AXE_SERVICEM8_OAUTH_SCOPES, AXE_SERVICEM8_OAUTH_TOKEN_URL, AXPAdministrationPermissionKeys, RootConfig };
|
|
184
|
-
export type { AXEServiceM8ConnectionConfig, AXEServiceM8ImportJobRequest, AXEServiceM8ImportJobResponse, AXEServiceM8JobsSyncState, AXEServiceM8OAuthCompleteRequest, AXEServiceM8OAuthCompleteResponse, AXEServiceM8OAuthStartRequest, AXEServiceM8OAuthStartResponse, AXEServiceM8OAuthValidateRequest, AXEServiceM8OAuthValidateResponse, AXEServiceM8PullJobsRequest, AXEServiceM8PullJobsResponse, AXEServiceM8RemoteJob, AXEServiceM8SyncPlatformProjectRequest };
|
|
255
|
+
export type { AXEServiceM8ConnectionConfig, AXEServiceM8ConnectionLifecycleRequest, AXEServiceM8ConnectionLifecycleResponse, AXEServiceM8ImportCustomerRequest, AXEServiceM8ImportCustomerResponse, AXEServiceM8ImportJobRequest, AXEServiceM8ImportJobResponse, AXEServiceM8JobsSyncState, AXEServiceM8OAuthCompleteRequest, AXEServiceM8OAuthCompleteResponse, AXEServiceM8OAuthStartRequest, AXEServiceM8OAuthStartResponse, AXEServiceM8OAuthValidateRequest, AXEServiceM8OAuthValidateResponse, AXEServiceM8PullJobsRequest, AXEServiceM8PullJobsResponse, AXEServiceM8RemoteCustomer, AXEServiceM8RemoteJob, AXEServiceM8RemoteSite, AXEServiceM8SyncPlatformProjectRequest };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-extension-project-management-servicem8-client-connect-servicem8.command-CkDOwDrg.mjs","sources":["../../../../libs/extensions/project-management/servicem8/client/src/lib/features/connect/servicem8-oauth.util.ts","../../../../libs/extensions/project-management/servicem8/client/src/lib/features/connect/connect-servicem8.command.ts"],"sourcesContent":["//#region ---- ServiceM8 OAuth helpers (client) ----\n\n/** Resolves the demo app path segment used in the OAuth callback URL. */\nexport function resolveServiceM8OAuthAppName(applicationName: string | null | undefined): string {\n const trimmed = String(applicationName ?? '').trim();\n return trimmed || 'demo';\n}\n\n//#endregion\n","//#region ---- Connect ServiceM8 (OAuth authorization code) ----\n\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n AXP_INTEGRATION_CONNECTION_STATUS,\n type AXPRuntimeCommandResult,\n type AXPIntegrationConnectionScope,\n} from '@acorex-platform/framework-shared/core';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\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 {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n type IActionBuilder,\n type IDialogBuilder,\n type IFlexContainerBuilder,\n type IFormFieldBuilder,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXEServiceM8OAuthHttpClient } from '../../api/servicem8-oauth-http.client';\nimport { Injectable, inject } from '@angular/core';\nimport { defaultTo, isEmpty, trim } from 'lodash-es';\nimport {\n AXE_SERVICEM8_API_BASE_URL,\n AXE_SERVICEM8_OAUTH_SCOPES,\n type AXEServiceM8ConnectionConfig,\n} from '@acorex-platform/extension-project-management-servicem8-client/contracts';\nimport type { AXMIntegrationManagementIntegrationConnectionEntityModel } from '@acorex-platform/module-integration-management-client/contracts';\nimport { resolveServiceM8OAuthAppName } from './servicem8-oauth.util';\n\nexport interface ConnectServiceM8CommandInput {\n providerId?: string;\n connectionScope?: AXPIntegrationConnectionScope;\n /** When set, reconfigure / reconnect this existing connection. */\n connectionId?: string;\n /** Optional explicit key; new connections get a generated key when omitted. */\n connectionKey?: string;\n}\n\ninterface AXEServiceM8ConnectFormContext {\n displayName: string;\n clientId: string;\n clientSecret: string;\n}\n\ninterface AXEServiceM8ConnectFormResult {\n displayName: string;\n clientId: string;\n clientSecret: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class ConnectServiceM8Command implements AXPCommand<ConnectServiceM8CommandInput, ConnectCommandResult> {\n private readonly connectionManager = inject(AXMIntegrationConnectionManager);\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly translationService = inject(AXTranslationService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly servicem8Http = inject(AXEServiceM8OAuthHttpClient);\n\n async execute(input: ConnectServiceM8CommandInput = {}): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n try {\n const providerId = input.providerId ?? 'servicem8';\n const connectionScope = input.connectionScope ?? 'tenant';\n const existing = await this.resolveExistingConnection(providerId, connectionScope, input);\n const isReconfigure = !!existing;\n const existingConfig = (existing?.config ?? {}) as AXEServiceM8ConnectionConfig;\n const connectionKey =\n existing?.connectionKey\n ?? (trim(input.connectionKey) || crypto.randomUUID());\n\n const title = await this.translationService.translateAsync(\n isReconfigure\n ? '@extensions-servicem8:integration.connect.dialog.reconfigure-title'\n : '@extensions-servicem8:integration.connect.dialog.title',\n );\n\n const form = await this.openConnectDialog({\n title: title ?? 'Connect ServiceM8',\n context: {\n displayName: existing?.displayName ?? 'ServiceM8',\n clientId: existingConfig.clientId ?? '',\n clientSecret: isReconfigure ? AXP_INTEGRATION_CREDENTIAL_MASK : '',\n },\n existing,\n existingConfig,\n isReconfigure,\n });\n\n if (!form) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n const credentialsChanged = this.credentialsChanged(existingConfig, form);\n const needsAuthorization = this.needsOAuthAuthorization(existingConfig, credentialsChanged);\n\n const config: AXEServiceM8ConnectionConfig = {\n clientId: form.clientId,\n clientSecret: form.clientSecret,\n scope: AXE_SERVICEM8_OAUTH_SCOPES,\n ...(credentialsChanged\n ? {}\n : {\n accessToken: existingConfig.accessToken,\n refreshToken: existingConfig.refreshToken,\n tokenExpiresAt: existingConfig.tokenExpiresAt,\n oauthTokenJson: existingConfig.oauthTokenJson,\n }),\n };\n\n const connection = await this.connectionManager.upsertConnection({\n providerId,\n authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.OAuth2,\n connectionScope,\n connectionKey,\n displayName: defaultTo(trim(form.displayName), 'ServiceM8'),\n instanceUrl: AXE_SERVICEM8_API_BASE_URL,\n externalAccountName: AXP_INTEGRATION_CREDENTIAL_MASK,\n config: config as Record<string, unknown>,\n status: needsAuthorization\n ? AXP_INTEGRATION_CONNECTION_STATUS.PendingAuthorization\n : AXP_INTEGRATION_CONNECTION_STATUS.Connected,\n isRevoked: false,\n isDisabled: false,\n });\n\n if (needsAuthorization) {\n const appName = resolveServiceM8OAuthAppName(this.sessionService.application?.name);\n const redirectUri = `${window.location.origin}/${appName}/integrations/oauth/callback/${providerId}`;\n const oauth = await this.servicem8Http.startOAuth({\n redirectUri,\n connectionId: connection.id,\n });\n return { success: true, kind: 'object',\n data: { outcome: 'redirect', redirectUrl: oauth.redirectUrl },\n };\n }\n\n const validation = await this.servicem8Http.validateOAuth({ connectionId: connection.id });\n if (!validation.valid) {\n return {\n success: false,\n message: { text: validation.message ?? 'ServiceM8 connection validation failed. Re-authorize ServiceM8.' },\n };\n }\n\n const refreshed = await this.connectionManager.getByIdForCurrentUser(connection.id);\n return { success: true, kind: 'object',\n data: {\n outcome: 'connected',\n connection: toSafeIntegrationConnectionDto(refreshed ?? connection),\n },\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to connect ServiceM8.';\n return { success: false, message: { text: message } };\n }\n }\n\n private async resolveExistingConnection(\n providerId: string,\n connectionScope: AXPIntegrationConnectionScope,\n input: ConnectServiceM8CommandInput,\n ): Promise<AXMIntegrationManagementIntegrationConnectionEntityModel | null> {\n if (input.connectionId) {\n const byId = await this.connectionManager.getByIdForCurrentUser(input.connectionId);\n if (!byId) {\n throw new Error('Connection not found or access denied.');\n }\n return byId;\n }\n\n const connectionKey = trim(input.connectionKey);\n if (!connectionKey) {\n return null;\n }\n\n return this.connectionManager.findByUniqueKey({\n providerId,\n connectionScope,\n connectionKey,\n });\n }\n\n private credentialsChanged(\n existingConfig: AXEServiceM8ConnectionConfig,\n form: AXEServiceM8ConnectFormResult,\n ): boolean {\n if (trim(form.clientId) !== trim(existingConfig.clientId ?? '')) {\n return true;\n }\n if (!isMaskedIntegrationCredential(form.clientSecret)) {\n return true;\n }\n return false;\n }\n\n private needsOAuthAuthorization(\n existingConfig: AXEServiceM8ConnectionConfig,\n credentialsChanged: boolean,\n ): boolean {\n if (credentialsChanged) {\n return true;\n }\n return isEmpty(trim(existingConfig.refreshToken ?? ''));\n }\n\n private async openConnectDialog(input: {\n title: string;\n context: AXEServiceM8ConnectFormContext;\n existing: AXMIntegrationManagementIntegrationConnectionEntityModel | null;\n existingConfig: AXEServiceM8ConnectionConfig;\n isReconfigure: boolean;\n }): Promise<AXEServiceM8ConnectFormResult | null> {\n const result: unknown = await this.layoutBuilder\n .create()\n .dialog<AXEServiceM8ConnectFormResult | null>((dialog: IDialogBuilder<AXEServiceM8ConnectFormResult | null>) => {\n dialog\n .setTitle(input.title)\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: '@extensions-servicem8:integration.connect.instructions',\n })\n .formField('@extensions-servicem8:integration.connect.fields.display-name', (field: IFormFieldBuilder) => {\n field.path('displayName');\n field.textBox({\n placeholder: '@extensions-servicem8:integration.connect.placeholders.display-name',\n });\n })\n .formField('@extensions-servicem8:integration.auth.oauth.client-id.label', (field) => {\n field.path('clientId');\n field.textBox({\n placeholder: '@extensions-servicem8:integration.auth.oauth.client-id.placeholder',\n validations: [{ rule: 'required' }],\n });\n })\n .formField('@extensions-servicem8:integration.auth.oauth.client-secret.label', (field) => {\n field.path('clientSecret');\n field.passwordBox({\n placeholder: '@extensions-servicem8:integration.auth.oauth.client-secret.placeholder',\n revealToggle: true,\n validations: input.isReconfigure ? [] : [{ rule: 'required' }],\n });\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit(\n input.isReconfigure && hasConfiguredIntegrationCredentials(input.existing)\n ? '@extensions-servicem8:integration.connect.actions.save'\n : '@extensions-servicem8:integration.connect.actions.save-and-authorize',\n );\n })\n .onAction(async (ref: AXPDialogRef) => {\n if (ref.action() === 'cancel') {\n return null;\n }\n\n const ctx = ref.context() as AXEServiceM8ConnectFormContext;\n const clientId = trim(ctx.clientId);\n if (!clientId) {\n throw new Error('ServiceM8 App ID is required.');\n }\n\n let clientSecret = trim(ctx.clientSecret);\n if (isMaskedIntegrationCredential(clientSecret) && input.existing) {\n clientSecret = trim(input.existingConfig.clientSecret ?? '');\n }\n if (!clientSecret) {\n throw new Error('ServiceM8 App Secret is required.');\n }\n\n return {\n displayName: trim(ctx.displayName) || 'ServiceM8',\n clientId,\n clientSecret,\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<AXEServiceM8ConnectFormResult>(result);\n }\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
|