pax8-cta 0.1.0
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/LICENSE +200 -0
- package/README.md +659 -0
- package/demo-data/solutions/ProductQADemo_1_0_0_2_managed.zip +0 -0
- package/dist/commands/analyze.d.ts +28 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +571 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/auth.d.ts +18 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +171 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/config.d.ts +34 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +299 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/demo.d.ts +33 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +362 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/deploy.d.ts +18 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +1186 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/deployments/helpers.d.ts +68 -0
- package/dist/commands/deployments/helpers.d.ts.map +1 -0
- package/dist/commands/deployments/helpers.js +414 -0
- package/dist/commands/deployments/helpers.js.map +1 -0
- package/dist/commands/deployments/index.d.ts +24 -0
- package/dist/commands/deployments/index.d.ts.map +1 -0
- package/dist/commands/deployments/index.js +47 -0
- package/dist/commands/deployments/index.js.map +1 -0
- package/dist/commands/deployments/list.d.ts +18 -0
- package/dist/commands/deployments/list.d.ts.map +1 -0
- package/dist/commands/deployments/list.js +97 -0
- package/dist/commands/deployments/list.js.map +1 -0
- package/dist/commands/deployments/show.d.ts +18 -0
- package/dist/commands/deployments/show.d.ts.map +1 -0
- package/dist/commands/deployments/show.js +81 -0
- package/dist/commands/deployments/show.js.map +1 -0
- package/dist/commands/deployments/undo.d.ts +18 -0
- package/dist/commands/deployments/undo.d.ts.map +1 -0
- package/dist/commands/deployments/undo.js +295 -0
- package/dist/commands/deployments/undo.js.map +1 -0
- package/dist/commands/export.d.ts +18 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +133 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/import.d.ts +18 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +129 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init-config.d.ts +26 -0
- package/dist/commands/init-config.d.ts.map +1 -0
- package/dist/commands/init-config.js +123 -0
- package/dist/commands/init-config.js.map +1 -0
- package/dist/commands/init-validation.d.ts +47 -0
- package/dist/commands/init-validation.d.ts.map +1 -0
- package/dist/commands/init-validation.js +339 -0
- package/dist/commands/init-validation.js.map +1 -0
- package/dist/commands/init-wizard.d.ts +25 -0
- package/dist/commands/init-wizard.d.ts.map +1 -0
- package/dist/commands/init-wizard.js +433 -0
- package/dist/commands/init-wizard.js.map +1 -0
- package/dist/commands/init.d.ts +18 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +46 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/resolve-url.d.ts +18 -0
- package/dist/commands/resolve-url.d.ts.map +1 -0
- package/dist/commands/resolve-url.js +126 -0
- package/dist/commands/resolve-url.js.map +1 -0
- package/dist/commands/setup.d.ts +18 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +239 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/solutions/drift-analysis.d.ts +73 -0
- package/dist/commands/solutions/drift-analysis.d.ts.map +1 -0
- package/dist/commands/solutions/drift-analysis.js +416 -0
- package/dist/commands/solutions/drift-analysis.js.map +1 -0
- package/dist/commands/solutions/drift.d.ts +32 -0
- package/dist/commands/solutions/drift.d.ts.map +1 -0
- package/dist/commands/solutions/drift.js +641 -0
- package/dist/commands/solutions/drift.js.map +1 -0
- package/dist/commands/solutions/fix-planner.d.ts +48 -0
- package/dist/commands/solutions/fix-planner.d.ts.map +1 -0
- package/dist/commands/solutions/fix-planner.js +43 -0
- package/dist/commands/solutions/fix-planner.js.map +1 -0
- package/dist/commands/solutions/helpers.d.ts +35 -0
- package/dist/commands/solutions/helpers.d.ts.map +1 -0
- package/dist/commands/solutions/helpers.js +54 -0
- package/dist/commands/solutions/helpers.js.map +1 -0
- package/dist/commands/solutions/index.d.ts +18 -0
- package/dist/commands/solutions/index.d.ts.map +1 -0
- package/dist/commands/solutions/index.js +30 -0
- package/dist/commands/solutions/index.js.map +1 -0
- package/dist/commands/solutions/list.d.ts +18 -0
- package/dist/commands/solutions/list.d.ts.map +1 -0
- package/dist/commands/solutions/list.js +174 -0
- package/dist/commands/solutions/list.js.map +1 -0
- package/dist/commands/solutions/remove.d.ts +18 -0
- package/dist/commands/solutions/remove.d.ts.map +1 -0
- package/dist/commands/solutions/remove.js +137 -0
- package/dist/commands/solutions/remove.js.map +1 -0
- package/dist/commands/solutions/risk-calculator.d.ts +33 -0
- package/dist/commands/solutions/risk-calculator.d.ts.map +1 -0
- package/dist/commands/solutions/risk-calculator.js +79 -0
- package/dist/commands/solutions/risk-calculator.js.map +1 -0
- package/dist/commands/solutions/show.d.ts +18 -0
- package/dist/commands/solutions/show.d.ts.map +1 -0
- package/dist/commands/solutions/show.js +165 -0
- package/dist/commands/solutions/show.js.map +1 -0
- package/dist/commands/status.d.ts +18 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +573 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/telemetry.d.ts +18 -0
- package/dist/commands/telemetry.d.ts.map +1 -0
- package/dist/commands/telemetry.js +85 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/tenants/health.d.ts +18 -0
- package/dist/commands/tenants/health.d.ts.map +1 -0
- package/dist/commands/tenants/health.js +172 -0
- package/dist/commands/tenants/health.js.map +1 -0
- package/dist/commands/tenants/helpers.d.ts +44 -0
- package/dist/commands/tenants/helpers.d.ts.map +1 -0
- package/dist/commands/tenants/helpers.js +72 -0
- package/dist/commands/tenants/helpers.js.map +1 -0
- package/dist/commands/tenants/index.d.ts +19 -0
- package/dist/commands/tenants/index.d.ts.map +1 -0
- package/dist/commands/tenants/index.js +39 -0
- package/dist/commands/tenants/index.js.map +1 -0
- package/dist/commands/tenants/inspect.d.ts +18 -0
- package/dist/commands/tenants/inspect.d.ts.map +1 -0
- package/dist/commands/tenants/inspect.js +176 -0
- package/dist/commands/tenants/inspect.js.map +1 -0
- package/dist/commands/tenants/list.d.ts +18 -0
- package/dist/commands/tenants/list.d.ts.map +1 -0
- package/dist/commands/tenants/list.js +144 -0
- package/dist/commands/tenants/list.js.map +1 -0
- package/dist/commands/tenants/manage.d.ts +20 -0
- package/dist/commands/tenants/manage.d.ts.map +1 -0
- package/dist/commands/tenants/manage.js +206 -0
- package/dist/commands/tenants/manage.js.map +1 -0
- package/dist/commands/tenants/show.d.ts +18 -0
- package/dist/commands/tenants/show.d.ts.map +1 -0
- package/dist/commands/tenants/show.js +191 -0
- package/dist/commands/tenants/show.js.map +1 -0
- package/dist/commands/validate.d.ts +18 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +536 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +258 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth.d.ts +51 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +153 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/banner.d.ts +19 -0
- package/dist/lib/banner.d.ts.map +1 -0
- package/dist/lib/banner.js +78 -0
- package/dist/lib/banner.js.map +1 -0
- package/dist/lib/command-wrapper.d.ts +56 -0
- package/dist/lib/command-wrapper.d.ts.map +1 -0
- package/dist/lib/command-wrapper.js +71 -0
- package/dist/lib/command-wrapper.js.map +1 -0
- package/dist/lib/credentials.d.ts +56 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +146 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/demo-banner.d.ts +15 -0
- package/dist/lib/demo-banner.d.ts.map +1 -0
- package/dist/lib/demo-banner.js +33 -0
- package/dist/lib/demo-banner.js.map +1 -0
- package/dist/lib/error-handler.d.ts +51 -0
- package/dist/lib/error-handler.d.ts.map +1 -0
- package/dist/lib/error-handler.js +458 -0
- package/dist/lib/error-handler.js.map +1 -0
- package/dist/lib/errors.d.ts +61 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +168 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/formatters.d.ts +55 -0
- package/dist/lib/formatters.d.ts.map +1 -0
- package/dist/lib/formatters.js +163 -0
- package/dist/lib/formatters.js.map +1 -0
- package/dist/lib/graph-client.d.ts +74 -0
- package/dist/lib/graph-client.d.ts.map +1 -0
- package/dist/lib/graph-client.js +231 -0
- package/dist/lib/graph-client.js.map +1 -0
- package/dist/lib/input.d.ts +22 -0
- package/dist/lib/input.d.ts.map +1 -0
- package/dist/lib/input.js +120 -0
- package/dist/lib/input.js.map +1 -0
- package/dist/lib/interactive-wizard.d.ts +26 -0
- package/dist/lib/interactive-wizard.d.ts.map +1 -0
- package/dist/lib/interactive-wizard.js +550 -0
- package/dist/lib/interactive-wizard.js.map +1 -0
- package/dist/lib/oss-surface.d.ts +21 -0
- package/dist/lib/oss-surface.d.ts.map +1 -0
- package/dist/lib/oss-surface.js +29 -0
- package/dist/lib/oss-surface.js.map +1 -0
- package/dist/lib/output.d.ts +74 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +156 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/picker.d.ts +75 -0
- package/dist/lib/picker.d.ts.map +1 -0
- package/dist/lib/picker.js +115 -0
- package/dist/lib/picker.js.map +1 -0
- package/dist/lib/repl.d.ts +19 -0
- package/dist/lib/repl.d.ts.map +1 -0
- package/dist/lib/repl.js +158 -0
- package/dist/lib/repl.js.map +1 -0
- package/dist/lib/spinner.d.ts +41 -0
- package/dist/lib/spinner.d.ts.map +1 -0
- package/dist/lib/spinner.js +126 -0
- package/dist/lib/spinner.js.map +1 -0
- package/dist/lib/telemetry.d.ts +96 -0
- package/dist/lib/telemetry.d.ts.map +1 -0
- package/dist/lib/telemetry.js +367 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Pax8, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import chalk from "chalk";
|
|
17
|
+
import { AuthError, GdapError, SolutionError, AgentResolutionError, ConfigValidationError, NetworkError, ErrorCode, isCtaError, } from "@pax8-cta/core";
|
|
18
|
+
const LEGACY_QUEUE_ERROR_MESSAGE = "Legacy deployment queue support is unavailable in the open-source CLI";
|
|
19
|
+
const LEGACY_QUEUE_ERROR_CAUSES = [
|
|
20
|
+
"A Redis-backed worker was referenced by older tooling or configuration",
|
|
21
|
+
"The CLI now deploys directly and does not use a queue",
|
|
22
|
+
"An outdated command or environment variable is still pointing at Redis",
|
|
23
|
+
];
|
|
24
|
+
const LEGACY_QUEUE_ERROR_RECOVERY = [
|
|
25
|
+
"Remove any legacy queue-related flags or configuration",
|
|
26
|
+
"Use the direct deployment flow instead:",
|
|
27
|
+
" deploy --direct --all --solution ./agent.zip",
|
|
28
|
+
"If this is coming from older automation, update it to call the direct CLI",
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Structured CLI error with recovery guidance.
|
|
32
|
+
*
|
|
33
|
+
* This wraps any error (typed or untyped) into a presentation-friendly
|
|
34
|
+
* format with causes, recovery steps, and context for the CLI output.
|
|
35
|
+
*/
|
|
36
|
+
export class CtaError extends Error {
|
|
37
|
+
code;
|
|
38
|
+
causes;
|
|
39
|
+
recovery;
|
|
40
|
+
context;
|
|
41
|
+
constructor(code, message, causes, recovery, context) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.code = code;
|
|
44
|
+
this.causes = causes;
|
|
45
|
+
this.recovery = recovery;
|
|
46
|
+
this.context = context;
|
|
47
|
+
this.name = "CtaError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Code-based mapping: structured errors from @pax8-cta/core
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
function formatByErrorCode(error) {
|
|
54
|
+
const ctx = {
|
|
55
|
+
environmentUrl: error.context?.environmentUrl,
|
|
56
|
+
tenantName: error.context?.tenantName,
|
|
57
|
+
solutionName: error.context?.solutionName,
|
|
58
|
+
clientId: error.context?.clientId,
|
|
59
|
+
};
|
|
60
|
+
// --- GDAP / App-user errors ---
|
|
61
|
+
if (error instanceof GdapError ||
|
|
62
|
+
error.code === ErrorCode.GDAP_MISSING ||
|
|
63
|
+
error.code === ErrorCode.GDAP_APP_USER_NOT_REGISTERED ||
|
|
64
|
+
error.code === ErrorCode.GDAP_SETUP_FAILED ||
|
|
65
|
+
error.code === ErrorCode.GDAP_ENVIRONMENT_ID_MISSING) {
|
|
66
|
+
return new CtaError("ERROR_GDAP_MISSING", "Application user not registered in Power Platform environment", [
|
|
67
|
+
"The application is not configured as a user in the target environment",
|
|
68
|
+
"The app registration may not have been added to the environment yet",
|
|
69
|
+
"GDAP (Granular Delegated Admin Privileges) relationship may not be established",
|
|
70
|
+
], [
|
|
71
|
+
"Go to https://admin.powerplatform.microsoft.com",
|
|
72
|
+
"Select the target environment \u2192 Settings \u2192 Users + permissions \u2192 Application users",
|
|
73
|
+
'Click "+ New app user" and add your application',
|
|
74
|
+
ctx.clientId
|
|
75
|
+
? `Use Client ID: ${ctx.clientId}`
|
|
76
|
+
: "Use the Client ID from your partner configuration",
|
|
77
|
+
'Assign the "System Administrator" security role',
|
|
78
|
+
"Save and retry the command",
|
|
79
|
+
], ctx);
|
|
80
|
+
}
|
|
81
|
+
// --- Permission / privilege errors ---
|
|
82
|
+
if (error.code === ErrorCode.PERMISSION_DENIED ||
|
|
83
|
+
error.code === ErrorCode.PERMISSION_PRIVILEGE_MISSING ||
|
|
84
|
+
error.code === ErrorCode.DATAVERSE_FORBIDDEN) {
|
|
85
|
+
return new CtaError("ERROR_INSUFFICIENT_PERMISSIONS", "Application user lacks required permissions in Power Platform environment", [
|
|
86
|
+
"The application user exists but doesn't have necessary security roles",
|
|
87
|
+
"The System Administrator role may not be assigned",
|
|
88
|
+
"Solution-specific permissions (prvReadSolution, prvWriteSolution, etc.) are missing",
|
|
89
|
+
], [
|
|
90
|
+
"Go to https://admin.powerplatform.microsoft.com",
|
|
91
|
+
"Select the target environment \u2192 Settings \u2192 Users + permissions \u2192 Application users",
|
|
92
|
+
ctx.clientId
|
|
93
|
+
? `Find your application user (Client ID: ${ctx.clientId})`
|
|
94
|
+
: "Find your application user",
|
|
95
|
+
'Click "Manage security roles" or "Edit"',
|
|
96
|
+
'Ensure "System Administrator" role is assigned',
|
|
97
|
+
"Verify the role includes solution deployment privileges (prvReadSolution, prvWriteSolution, prvCreateSolution)",
|
|
98
|
+
"Save and retry the command",
|
|
99
|
+
], ctx);
|
|
100
|
+
}
|
|
101
|
+
// --- Authentication errors ---
|
|
102
|
+
if (error instanceof AuthError ||
|
|
103
|
+
error.code === ErrorCode.DATAVERSE_UNAUTHORIZED ||
|
|
104
|
+
error.code === ErrorCode.AUTH_FAILED ||
|
|
105
|
+
error.code === ErrorCode.AUTH_TOKEN_EXPIRED ||
|
|
106
|
+
error.code === ErrorCode.AUTH_APP_NOT_FOUND ||
|
|
107
|
+
error.code === ErrorCode.AUTH_INVALID_SECRET ||
|
|
108
|
+
error.code === ErrorCode.AUTH_ACCOUNT_NOT_FOUND ||
|
|
109
|
+
error.code === ErrorCode.AUTH_INVALID_CLIENT) {
|
|
110
|
+
return new CtaError("ERROR_AUTH_FAILED", "Authentication failed - unable to acquire or validate access token", [
|
|
111
|
+
"The client secret may have expired",
|
|
112
|
+
"API permissions may not be configured correctly in Azure AD",
|
|
113
|
+
"Admin consent may not have been granted for the required permissions",
|
|
114
|
+
], [
|
|
115
|
+
"Verify the app registration in Azure Portal:",
|
|
116
|
+
" - Go to https://portal.azure.com \u2192 Azure Active Directory \u2192 App registrations",
|
|
117
|
+
ctx.clientId
|
|
118
|
+
? ` - Find your app (Client ID: ${ctx.clientId})`
|
|
119
|
+
: " - Locate your application registration",
|
|
120
|
+
"Check API permissions:",
|
|
121
|
+
' - Ensure "Dynamics CRM" or "Common Data Service" API permission is added',
|
|
122
|
+
' - Permission should be "user_impersonation" (delegated) or ".default" (application)',
|
|
123
|
+
' - Click "Grant admin consent" if not already done',
|
|
124
|
+
"Verify client secret:",
|
|
125
|
+
" - Check if the secret has expired in the app registration",
|
|
126
|
+
" - Generate a new secret if needed and update your environment variable (PARTNER_CLIENT_SECRET)",
|
|
127
|
+
"Retry the command",
|
|
128
|
+
], ctx);
|
|
129
|
+
}
|
|
130
|
+
// --- Solution not found ---
|
|
131
|
+
if (error instanceof SolutionError ||
|
|
132
|
+
error.code === ErrorCode.SOLUTION_NOT_FOUND ||
|
|
133
|
+
error.code === ErrorCode.SOLUTION_IMPORT_FAILED ||
|
|
134
|
+
error.code === ErrorCode.SOLUTION_EXPORT_FAILED) {
|
|
135
|
+
return new CtaError("ERROR_SOLUTION_NOT_FOUND", ctx.solutionName
|
|
136
|
+
? `Solution '${ctx.solutionName}' not found in environment`
|
|
137
|
+
: "Solution not found in environment", [
|
|
138
|
+
"The solution may not exist in the source environment",
|
|
139
|
+
"The solution name may be misspelled (names are case-sensitive)",
|
|
140
|
+
"The solution may have been deleted or renamed",
|
|
141
|
+
], [
|
|
142
|
+
ctx.solutionName
|
|
143
|
+
? `Verify the solution name '${ctx.solutionName}' is correct`
|
|
144
|
+
: "Verify the solution name is correct and matches exactly (case-sensitive)",
|
|
145
|
+
"List available solutions in the source environment:",
|
|
146
|
+
" agents list",
|
|
147
|
+
"Check that you're connected to the correct source environment",
|
|
148
|
+
"Ensure the solution is published and visible in the source environment",
|
|
149
|
+
"Retry with the correct solution name",
|
|
150
|
+
], ctx);
|
|
151
|
+
}
|
|
152
|
+
// --- Agent resolution errors ---
|
|
153
|
+
if (error instanceof AgentResolutionError) {
|
|
154
|
+
return new CtaError("ERROR_SOLUTION_NOT_FOUND", "Could not resolve agent URL to a solution", [
|
|
155
|
+
"The agent URL may be invalid or the agent no longer exists",
|
|
156
|
+
"The titleId in the URL may not match any bot in the environment",
|
|
157
|
+
"The M365 Graph API may be needed to resolve this URL format",
|
|
158
|
+
], [
|
|
159
|
+
"Verify the agent URL is correct and the agent is published",
|
|
160
|
+
"List available agents in the source environment:",
|
|
161
|
+
" agents list",
|
|
162
|
+
"Try using the solution name directly instead of the agent URL",
|
|
163
|
+
], ctx);
|
|
164
|
+
}
|
|
165
|
+
// --- Network errors ---
|
|
166
|
+
if (error instanceof NetworkError ||
|
|
167
|
+
error.code === ErrorCode.NETWORK_CONNECTION_REFUSED ||
|
|
168
|
+
error.code === ErrorCode.NETWORK_TIMEOUT ||
|
|
169
|
+
error.code === ErrorCode.NETWORK_DNS_FAILED ||
|
|
170
|
+
error.code === ErrorCode.NETWORK_ERROR) {
|
|
171
|
+
return new CtaError("ERROR_NETWORK", "Network connection failed", [
|
|
172
|
+
"The target environment URL may be incorrect or unreachable",
|
|
173
|
+
"Network connectivity issues (firewall, proxy, DNS)",
|
|
174
|
+
"The Power Platform environment may be temporarily unavailable",
|
|
175
|
+
], [
|
|
176
|
+
"Verify the environment URL is correct:",
|
|
177
|
+
ctx.environmentUrl
|
|
178
|
+
? ` Current: ${ctx.environmentUrl}`
|
|
179
|
+
: " Check your configuration file for the correct URL",
|
|
180
|
+
"Test network connectivity:",
|
|
181
|
+
ctx.environmentUrl
|
|
182
|
+
? ` curl -I ${ctx.environmentUrl}`
|
|
183
|
+
: " Use curl or ping to test the environment URL",
|
|
184
|
+
"Check firewall/proxy settings that may block Power Platform endpoints",
|
|
185
|
+
"Verify DNS resolution for the environment hostname",
|
|
186
|
+
"If using a VPN, ensure it's connected and configured properly",
|
|
187
|
+
"Check Power Platform service status: https://admin.powerplatform.microsoft.com/service-health",
|
|
188
|
+
"Retry the command after resolving connectivity issues",
|
|
189
|
+
], ctx);
|
|
190
|
+
}
|
|
191
|
+
// --- Config errors ---
|
|
192
|
+
if (error instanceof ConfigValidationError ||
|
|
193
|
+
error.code === ErrorCode.CONFIG_NOT_FOUND ||
|
|
194
|
+
error.code === ErrorCode.CONFIG_INVALID ||
|
|
195
|
+
error.code === ErrorCode.CONFIG_READ_FAILED ||
|
|
196
|
+
error.code === ErrorCode.CONFIG_PARSE_FAILED ||
|
|
197
|
+
error.code === ErrorCode.CONFIG_SECRET_MISSING) {
|
|
198
|
+
return new CtaError("ERROR_CONFIG_NOT_FOUND", "Configuration file or required resource not found", [
|
|
199
|
+
"The configuration file may not exist at the specified path",
|
|
200
|
+
"The working directory may be incorrect",
|
|
201
|
+
"Required files may have been deleted or moved",
|
|
202
|
+
], [
|
|
203
|
+
"Verify you're in the correct directory (should contain config/ folder)",
|
|
204
|
+
"Check if the configuration file exists:",
|
|
205
|
+
" ls -la ./config/tenants.yaml",
|
|
206
|
+
"If the config file doesn't exist, initialize a new configuration:",
|
|
207
|
+
" init",
|
|
208
|
+
"Specify a custom config path with --config flag if needed:",
|
|
209
|
+
" deploy --config /path/to/config.yaml ...",
|
|
210
|
+
], ctx);
|
|
211
|
+
}
|
|
212
|
+
// --- Queue / Redis errors ---
|
|
213
|
+
if (error.code === ErrorCode.QUEUE_CONNECTION_FAILED) {
|
|
214
|
+
return new CtaError("ERROR_QUEUE_CONNECTION", LEGACY_QUEUE_ERROR_MESSAGE, LEGACY_QUEUE_ERROR_CAUSES, LEGACY_QUEUE_ERROR_RECOVERY, ctx);
|
|
215
|
+
}
|
|
216
|
+
// Unknown code from core - fall through to regex
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
// Regex-based fallback for untyped errors
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
function formatByRegex(error) {
|
|
223
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
224
|
+
const errorString = errorMessage.toLowerCase();
|
|
225
|
+
// Extract context from error message
|
|
226
|
+
const environmentUrlMatch = errorMessage.match(/environment:?\s+(https?:\/\/[^\s]+)/i);
|
|
227
|
+
const clientIdMatch = errorMessage.match(/client\s+id:?\s+([a-f0-9-]+)/i);
|
|
228
|
+
const context = {};
|
|
229
|
+
if (environmentUrlMatch) {
|
|
230
|
+
context.environmentUrl = environmentUrlMatch[1];
|
|
231
|
+
}
|
|
232
|
+
if (clientIdMatch) {
|
|
233
|
+
context.clientId = clientIdMatch[1];
|
|
234
|
+
}
|
|
235
|
+
// GDAP/App user missing
|
|
236
|
+
if (errorString.includes("not a member of the organization") ||
|
|
237
|
+
errorString.includes("not a member of") ||
|
|
238
|
+
errorString.includes("application is not registered")) {
|
|
239
|
+
return new CtaError("ERROR_GDAP_MISSING", "Application user not registered in Power Platform environment", [
|
|
240
|
+
"The application is not configured as a user in the target environment",
|
|
241
|
+
"The app registration may not have been added to the environment yet",
|
|
242
|
+
"GDAP (Granular Delegated Admin Privileges) relationship may not be established",
|
|
243
|
+
], [
|
|
244
|
+
"Go to https://admin.powerplatform.microsoft.com",
|
|
245
|
+
"Select the target environment \u2192 Settings \u2192 Users + permissions \u2192 Application users",
|
|
246
|
+
'Click "+ New app user" and add your application',
|
|
247
|
+
context.clientId
|
|
248
|
+
? `Use Client ID: ${context.clientId}`
|
|
249
|
+
: "Use the Client ID from your partner configuration",
|
|
250
|
+
'Assign the "System Administrator" security role',
|
|
251
|
+
"Save and retry the command",
|
|
252
|
+
], context);
|
|
253
|
+
}
|
|
254
|
+
// Permission/privilege errors
|
|
255
|
+
if (errorString.includes("prvread") ||
|
|
256
|
+
errorString.includes("prvwrite") ||
|
|
257
|
+
errorString.includes("prvcreate") ||
|
|
258
|
+
errorString.includes("prvdelete") ||
|
|
259
|
+
errorString.includes("privilege") ||
|
|
260
|
+
errorString.includes("insufficient") ||
|
|
261
|
+
errorString.includes("access") ||
|
|
262
|
+
errorString.includes("403")) {
|
|
263
|
+
return new CtaError("ERROR_INSUFFICIENT_PERMISSIONS", "Application user lacks required permissions in Power Platform environment", [
|
|
264
|
+
"The application user exists but doesn't have necessary security roles",
|
|
265
|
+
"The System Administrator role may not be assigned",
|
|
266
|
+
"Solution-specific permissions (prvReadSolution, prvWriteSolution, etc.) are missing",
|
|
267
|
+
], [
|
|
268
|
+
"Go to https://admin.powerplatform.microsoft.com",
|
|
269
|
+
"Select the target environment \u2192 Settings \u2192 Users + permissions \u2192 Application users",
|
|
270
|
+
context.clientId
|
|
271
|
+
? `Find your application user (Client ID: ${context.clientId})`
|
|
272
|
+
: "Find your application user",
|
|
273
|
+
'Click "Manage security roles" or "Edit"',
|
|
274
|
+
'Ensure "System Administrator" role is assigned',
|
|
275
|
+
"Verify the role includes solution deployment privileges (prvReadSolution, prvWriteSolution, prvCreateSolution)",
|
|
276
|
+
"Save and retry the command",
|
|
277
|
+
], context);
|
|
278
|
+
}
|
|
279
|
+
// Authentication/token errors
|
|
280
|
+
if (errorString.includes("401") ||
|
|
281
|
+
errorString.includes("unauthorized") ||
|
|
282
|
+
errorString.includes("authentication failed") ||
|
|
283
|
+
errorString.includes("token")) {
|
|
284
|
+
return new CtaError("ERROR_AUTH_FAILED", "Authentication failed - unable to acquire or validate access token", [
|
|
285
|
+
"The client secret may have expired",
|
|
286
|
+
"API permissions may not be configured correctly in Azure AD",
|
|
287
|
+
"Admin consent may not have been granted for the required permissions",
|
|
288
|
+
], [
|
|
289
|
+
"Verify the app registration in Azure Portal:",
|
|
290
|
+
" - Go to https://portal.azure.com \u2192 Azure Active Directory \u2192 App registrations",
|
|
291
|
+
context.clientId
|
|
292
|
+
? ` - Find your app (Client ID: ${context.clientId})`
|
|
293
|
+
: " - Locate your application registration",
|
|
294
|
+
"Check API permissions:",
|
|
295
|
+
' - Ensure "Dynamics CRM" or "Common Data Service" API permission is added',
|
|
296
|
+
' - Permission should be "user_impersonation" (delegated) or ".default" (application)',
|
|
297
|
+
' - Click "Grant admin consent" if not already done',
|
|
298
|
+
"Verify client secret:",
|
|
299
|
+
" - Check if the secret has expired in the app registration",
|
|
300
|
+
" - Generate a new secret if needed and update your environment variable (PARTNER_CLIENT_SECRET)",
|
|
301
|
+
"Retry the command",
|
|
302
|
+
], context);
|
|
303
|
+
}
|
|
304
|
+
// Solution not found
|
|
305
|
+
if ((errorString.includes("not found") || errorString.includes("404")) &&
|
|
306
|
+
(errorString.includes("solution") || errorString.includes("agent"))) {
|
|
307
|
+
// Try to extract solution name from message
|
|
308
|
+
const solutionMatch = errorMessage.match(/solution\s+'([^']+)'|solution\s+"([^"]+)"/i);
|
|
309
|
+
if (solutionMatch) {
|
|
310
|
+
context.solutionName = solutionMatch[1] || solutionMatch[2];
|
|
311
|
+
}
|
|
312
|
+
return new CtaError("ERROR_SOLUTION_NOT_FOUND", context.solutionName
|
|
313
|
+
? `Solution '${context.solutionName}' not found in environment`
|
|
314
|
+
: "Solution not found in environment", [
|
|
315
|
+
"The solution may not exist in the source environment",
|
|
316
|
+
"The solution name may be misspelled (names are case-sensitive)",
|
|
317
|
+
"The solution may have been deleted or renamed",
|
|
318
|
+
], [
|
|
319
|
+
context.solutionName
|
|
320
|
+
? `Verify the solution name '${context.solutionName}' is correct`
|
|
321
|
+
: "Verify the solution name is correct and matches exactly (case-sensitive)",
|
|
322
|
+
"List available solutions in the source environment:",
|
|
323
|
+
" solutions list",
|
|
324
|
+
"Check that you're connected to the correct source environment",
|
|
325
|
+
"Ensure the solution is published and visible in the source environment",
|
|
326
|
+
"Retry with the correct solution name",
|
|
327
|
+
], context);
|
|
328
|
+
}
|
|
329
|
+
// Network errors
|
|
330
|
+
if (errorString.includes("econnrefused") ||
|
|
331
|
+
errorString.includes("etimedout") ||
|
|
332
|
+
errorString.includes("enotfound") ||
|
|
333
|
+
errorString.includes("network") ||
|
|
334
|
+
errorString.includes("fetch failed")) {
|
|
335
|
+
return new CtaError("ERROR_NETWORK", "Network connection failed", [
|
|
336
|
+
"The target environment URL may be incorrect or unreachable",
|
|
337
|
+
"Network connectivity issues (firewall, proxy, DNS)",
|
|
338
|
+
"The Power Platform environment may be temporarily unavailable",
|
|
339
|
+
], [
|
|
340
|
+
"Verify the environment URL is correct:",
|
|
341
|
+
context.environmentUrl
|
|
342
|
+
? ` Current: ${context.environmentUrl}`
|
|
343
|
+
: " Check your configuration file for the correct URL",
|
|
344
|
+
"Test network connectivity:",
|
|
345
|
+
context.environmentUrl
|
|
346
|
+
? ` curl -I ${context.environmentUrl}`
|
|
347
|
+
: " Use curl or ping to test the environment URL",
|
|
348
|
+
"Check firewall/proxy settings that may block Power Platform endpoints",
|
|
349
|
+
"Verify DNS resolution for the environment hostname",
|
|
350
|
+
"If using a VPN, ensure it's connected and configured properly",
|
|
351
|
+
"Check Power Platform service status: https://admin.powerplatform.microsoft.com/service-health",
|
|
352
|
+
"Retry the command after resolving connectivity issues",
|
|
353
|
+
], context);
|
|
354
|
+
}
|
|
355
|
+
// Config/file not found
|
|
356
|
+
if (errorString.includes("not found") &&
|
|
357
|
+
(errorString.includes("config") ||
|
|
358
|
+
errorString.includes("file") ||
|
|
359
|
+
errorString.includes("enoent"))) {
|
|
360
|
+
return new CtaError("ERROR_CONFIG_NOT_FOUND", "Configuration file or required resource not found", [
|
|
361
|
+
"The configuration file may not exist at the specified path",
|
|
362
|
+
"The working directory may be incorrect",
|
|
363
|
+
"Required files may have been deleted or moved",
|
|
364
|
+
], [
|
|
365
|
+
"Verify you're in the correct directory (should contain config/ folder)",
|
|
366
|
+
"Check if the configuration file exists:",
|
|
367
|
+
" ls -la ./config/tenants.yaml",
|
|
368
|
+
"If the config file doesn't exist, initialize a new configuration:",
|
|
369
|
+
" init",
|
|
370
|
+
"Specify a custom config path with --config flag if needed:",
|
|
371
|
+
" deploy --config /path/to/config.yaml ...",
|
|
372
|
+
], context);
|
|
373
|
+
}
|
|
374
|
+
// Redis/queue connection errors
|
|
375
|
+
if (errorString.includes("redis") ||
|
|
376
|
+
errorString.includes("queue") ||
|
|
377
|
+
(errorString.includes("connection") && errorString.includes("refused"))) {
|
|
378
|
+
return new CtaError("ERROR_QUEUE_CONNECTION", LEGACY_QUEUE_ERROR_MESSAGE, LEGACY_QUEUE_ERROR_CAUSES, LEGACY_QUEUE_ERROR_RECOVERY, context);
|
|
379
|
+
}
|
|
380
|
+
// Generic fallback
|
|
381
|
+
return new CtaError("ERROR_UNKNOWN", errorMessage, [
|
|
382
|
+
"An unexpected error occurred",
|
|
383
|
+
"The error details are shown above",
|
|
384
|
+
"This may be a temporary issue or a bug in Pax8 CTA",
|
|
385
|
+
], [
|
|
386
|
+
"Review the error message above for specific details",
|
|
387
|
+
"Check the Pax8 CTA documentation for common issues",
|
|
388
|
+
"Verify your configuration and environment setup",
|
|
389
|
+
"Try the command again with --verbose flag for more details (if available)",
|
|
390
|
+
"If the issue persists, please report it on GitHub with the error details",
|
|
391
|
+
" https://github.com/pax8labs/pax8-cta/issues",
|
|
392
|
+
], context);
|
|
393
|
+
}
|
|
394
|
+
// ---------------------------------------------------------------------------
|
|
395
|
+
// Public API
|
|
396
|
+
// ---------------------------------------------------------------------------
|
|
397
|
+
/**
|
|
398
|
+
* Maps any error to a structured CtaError with recovery guidance.
|
|
399
|
+
*
|
|
400
|
+
* 1. If the error is a typed CtaError from @pax8-cta/core, the
|
|
401
|
+
* error code is used to select the appropriate guidance (no regex).
|
|
402
|
+
* 2. Otherwise, falls back to regex matching on the error message.
|
|
403
|
+
*/
|
|
404
|
+
export function formatError(error) {
|
|
405
|
+
// Fast path: structured error from core with a known code
|
|
406
|
+
if (isCtaError(error)) {
|
|
407
|
+
const result = formatByErrorCode(error);
|
|
408
|
+
if (result) {
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// Slow path: regex fallback for plain Error / string / unknown
|
|
413
|
+
return formatByRegex(error);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Prints a formatted error message with recovery guidance
|
|
417
|
+
*/
|
|
418
|
+
export function printError(error) {
|
|
419
|
+
console.error();
|
|
420
|
+
console.error(chalk.red.bold(`Error: ${error.message}`), chalk.gray(`(${error.code})`));
|
|
421
|
+
console.error();
|
|
422
|
+
// Possible causes
|
|
423
|
+
console.error(chalk.yellow.bold("Possible causes:"));
|
|
424
|
+
error.causes.forEach((cause) => {
|
|
425
|
+
console.error(chalk.yellow(` \u2022 ${cause}`));
|
|
426
|
+
});
|
|
427
|
+
console.error();
|
|
428
|
+
// Recovery steps
|
|
429
|
+
console.error(chalk.cyan.bold("To fix:"));
|
|
430
|
+
error.recovery.forEach((step, index) => {
|
|
431
|
+
// Check if this is a sub-step (starts with spaces/dash)
|
|
432
|
+
if (step.startsWith(" ")) {
|
|
433
|
+
console.error(chalk.cyan(` ${step.trim()}`));
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
console.error(chalk.cyan(` ${index + 1}. ${step}`));
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
console.error();
|
|
440
|
+
// Context information
|
|
441
|
+
if (error.context && Object.keys(error.context).length > 0) {
|
|
442
|
+
console.error(chalk.gray.bold("Context:"));
|
|
443
|
+
if (error.context.environmentUrl) {
|
|
444
|
+
console.error(chalk.gray(` Environment: ${error.context.environmentUrl}`));
|
|
445
|
+
}
|
|
446
|
+
if (error.context.tenantName) {
|
|
447
|
+
console.error(chalk.gray(` Tenant: ${error.context.tenantName}`));
|
|
448
|
+
}
|
|
449
|
+
if (error.context.solutionName) {
|
|
450
|
+
console.error(chalk.gray(` Solution: ${error.context.solutionName}`));
|
|
451
|
+
}
|
|
452
|
+
if (error.context.clientId) {
|
|
453
|
+
console.error(chalk.gray(` Client ID: ${error.context.clientId}`));
|
|
454
|
+
}
|
|
455
|
+
console.error();
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/lib/error-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Pax8, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Base CLI error with exit code.
|
|
18
|
+
* Exit code 1 = runtime error (config not found, network failure, etc.)
|
|
19
|
+
*/
|
|
20
|
+
export declare class CliError extends Error {
|
|
21
|
+
exitCode: number;
|
|
22
|
+
constructor(message: string, exitCode?: number);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Usage error — invalid options, missing required args, etc.
|
|
26
|
+
* Exit code 2.
|
|
27
|
+
*/
|
|
28
|
+
export declare class UsageError extends CliError {
|
|
29
|
+
constructor(message: string);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Spinner-like interface for cleanup. Matches the ora spinner API subset we use.
|
|
33
|
+
*/
|
|
34
|
+
interface SpinnerLike {
|
|
35
|
+
fail: (text?: string) => void;
|
|
36
|
+
isSpinning?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Detect whether JSON output mode is active.
|
|
40
|
+
*
|
|
41
|
+
* Two signals (OR'd):
|
|
42
|
+
* 1. `--json` is present anywhere in process.argv (simple substring check).
|
|
43
|
+
* 2. stdout is not a TTY (piped/redirected).
|
|
44
|
+
*
|
|
45
|
+
* Exported so that issue #345 (proper Commander-driven --json flag) can replace
|
|
46
|
+
* this with a single authoritative source of truth once that flag lands.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isJsonOutputMode(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Standard error handler for CLI commands.
|
|
51
|
+
*
|
|
52
|
+
* - Stops the spinner with a fail message
|
|
53
|
+
* - When JSON mode is active (--json flag or piped stdout), emits a single JSON
|
|
54
|
+
* object to stderr with structured `code`, `message`, `causes`, and `recovery`
|
|
55
|
+
* fields — suitable for LLM-agent consumption.
|
|
56
|
+
* - Otherwise, uses the human-formatted handler (formatError/printError).
|
|
57
|
+
* - Exits with the appropriate code (1=runtime, 2=usage).
|
|
58
|
+
*/
|
|
59
|
+
export declare function handleCommandError(error: unknown, spinner?: SpinnerLike | null, failMessage?: string): never;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH;;;GAGG;AACH,qBAAa,QAAS,SAAQ,KAAK;IAGxB,QAAQ,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACR,QAAQ,GAAE,MAAU;CAK9B;AAED;;;GAGG;AACH,qBAAa,UAAW,SAAQ,QAAQ;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAsFD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,EAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,KAAK,CA8BP"}
|