@pax8-cta/core 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 +198 -0
- package/dist/auth/device-code-login.d.ts +40 -0
- package/dist/auth/device-code-login.d.ts.map +1 -0
- package/dist/auth/device-code-login.js +59 -0
- package/dist/auth/device-code-login.js.map +1 -0
- package/dist/auth/gdap-client.d.ts +81 -0
- package/dist/auth/gdap-client.d.ts.map +1 -0
- package/dist/auth/gdap-client.js +128 -0
- package/dist/auth/gdap-client.js.map +1 -0
- package/dist/auth/index.d.ts +19 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +19 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token-manager.d.ts +54 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +150 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/client.d.ts +27 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +27 -0
- package/dist/client.js.map +1 -0
- package/dist/config/client.d.ts +24 -0
- package/dist/config/client.d.ts.map +1 -0
- package/dist/config/client.js +18 -0
- package/dist/config/client.js.map +1 -0
- package/dist/config/index.d.ts +18 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +18 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +81 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +271 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +751 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +556 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants.d.ts +116 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +170 -0
- package/dist/constants.js.map +1 -0
- package/dist/dataverse/agent-resolver.d.ts +98 -0
- package/dist/dataverse/agent-resolver.d.ts.map +1 -0
- package/dist/dataverse/agent-resolver.js +185 -0
- package/dist/dataverse/agent-resolver.js.map +1 -0
- package/dist/dataverse/client.d.ts +104 -0
- package/dist/dataverse/client.d.ts.map +1 -0
- package/dist/dataverse/client.js +272 -0
- package/dist/dataverse/client.js.map +1 -0
- package/dist/dataverse/connection-refs.d.ts +115 -0
- package/dist/dataverse/connection-refs.d.ts.map +1 -0
- package/dist/dataverse/connection-refs.js +203 -0
- package/dist/dataverse/connection-refs.js.map +1 -0
- package/dist/dataverse/index.d.ts +20 -0
- package/dist/dataverse/index.d.ts.map +1 -0
- package/dist/dataverse/index.js +20 -0
- package/dist/dataverse/index.js.map +1 -0
- package/dist/dataverse/solution-ops.d.ts +100 -0
- package/dist/dataverse/solution-ops.d.ts.map +1 -0
- package/dist/dataverse/solution-ops.js +288 -0
- package/dist/dataverse/solution-ops.js.map +1 -0
- package/dist/errors.d.ts +171 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +178 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/mock/demo-data.d.ts +213 -0
- package/dist/mock/demo-data.d.ts.map +1 -0
- package/dist/mock/demo-data.js +1096 -0
- package/dist/mock/demo-data.js.map +1 -0
- package/dist/mock/demo-deployment-store.d.ts +77 -0
- package/dist/mock/demo-deployment-store.d.ts.map +1 -0
- package/dist/mock/demo-deployment-store.js +85 -0
- package/dist/mock/demo-deployment-store.js.map +1 -0
- package/dist/powerplatform/admin-client.d.ts +226 -0
- package/dist/powerplatform/admin-client.d.ts.map +1 -0
- package/dist/powerplatform/admin-client.js +315 -0
- package/dist/powerplatform/admin-client.js.map +1 -0
- package/dist/powerplatform/index.d.ts +18 -0
- package/dist/powerplatform/index.d.ts.map +1 -0
- package/dist/powerplatform/index.js +18 -0
- package/dist/powerplatform/index.js.map +1 -0
- package/dist/powerplatform/tenant-discovery.d.ts +100 -0
- package/dist/powerplatform/tenant-discovery.d.ts.map +1 -0
- package/dist/powerplatform/tenant-discovery.js +205 -0
- package/dist/powerplatform/tenant-discovery.js.map +1 -0
- package/dist/preconditions/check.d.ts +41 -0
- package/dist/preconditions/check.d.ts.map +1 -0
- package/dist/preconditions/check.js +173 -0
- package/dist/preconditions/check.js.map +1 -0
- package/dist/preconditions/index.d.ts +20 -0
- package/dist/preconditions/index.d.ts.map +1 -0
- package/dist/preconditions/index.js +20 -0
- package/dist/preconditions/index.js.map +1 -0
- package/dist/preconditions/loader.d.ts +33 -0
- package/dist/preconditions/loader.d.ts.map +1 -0
- package/dist/preconditions/loader.js +65 -0
- package/dist/preconditions/loader.js.map +1 -0
- package/dist/preconditions/schema.d.ts +103 -0
- package/dist/preconditions/schema.d.ts.map +1 -0
- package/dist/preconditions/schema.js +93 -0
- package/dist/preconditions/schema.js.map +1 -0
- package/dist/preconditions/types.d.ts +118 -0
- package/dist/preconditions/types.d.ts.map +1 -0
- package/dist/preconditions/types.js +17 -0
- package/dist/preconditions/types.js.map +1 -0
- package/dist/queue/index.d.ts +17 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +17 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/memory-queue.d.ts +86 -0
- package/dist/queue/memory-queue.d.ts.map +1 -0
- package/dist/queue/memory-queue.js +221 -0
- package/dist/queue/memory-queue.js.map +1 -0
- package/dist/services/audit-log.d.ts +59 -0
- package/dist/services/audit-log.d.ts.map +1 -0
- package/dist/services/audit-log.js +193 -0
- package/dist/services/audit-log.js.map +1 -0
- package/dist/services/auth-error-parser.d.ts +36 -0
- package/dist/services/auth-error-parser.d.ts.map +1 -0
- package/dist/services/auth-error-parser.js +90 -0
- package/dist/services/auth-error-parser.js.map +1 -0
- package/dist/services/deployment-doctor.d.ts +109 -0
- package/dist/services/deployment-doctor.d.ts.map +1 -0
- package/dist/services/deployment-doctor.js +476 -0
- package/dist/services/deployment-doctor.js.map +1 -0
- package/dist/services/deployment-notifications.d.ts +41 -0
- package/dist/services/deployment-notifications.d.ts.map +1 -0
- package/dist/services/deployment-notifications.js +161 -0
- package/dist/services/deployment-notifications.js.map +1 -0
- package/dist/services/deployment-progress.d.ts +89 -0
- package/dist/services/deployment-progress.d.ts.map +1 -0
- package/dist/services/deployment-progress.js +244 -0
- package/dist/services/deployment-progress.js.map +1 -0
- package/dist/services/deployment-service.d.ts +97 -0
- package/dist/services/deployment-service.d.ts.map +1 -0
- package/dist/services/deployment-service.js +375 -0
- package/dist/services/deployment-service.js.map +1 -0
- package/dist/services/drift-analyzer.d.ts +86 -0
- package/dist/services/drift-analyzer.d.ts.map +1 -0
- package/dist/services/drift-analyzer.js +273 -0
- package/dist/services/drift-analyzer.js.map +1 -0
- package/dist/services/environment-setup.d.ts +97 -0
- package/dist/services/environment-setup.d.ts.map +1 -0
- package/dist/services/environment-setup.js +250 -0
- package/dist/services/environment-setup.js.map +1 -0
- package/dist/services/health-check.d.ts +168 -0
- package/dist/services/health-check.d.ts.map +1 -0
- package/dist/services/health-check.js +705 -0
- package/dist/services/health-check.js.map +1 -0
- package/dist/services/index.d.ts +39 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +39 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/logger.d.ts +139 -0
- package/dist/services/logger.d.ts.map +1 -0
- package/dist/services/logger.js +268 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/services/notification-service.d.ts +55 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +184 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/risk-analyzer.d.ts +252 -0
- package/dist/services/risk-analyzer.d.ts.map +1 -0
- package/dist/services/risk-analyzer.js +866 -0
- package/dist/services/risk-analyzer.js.map +1 -0
- package/dist/services/rollback.d.ts +57 -0
- package/dist/services/rollback.d.ts.map +1 -0
- package/dist/services/rollback.js +270 -0
- package/dist/services/rollback.js.map +1 -0
- package/dist/services/scheduler.d.ts +80 -0
- package/dist/services/scheduler.d.ts.map +1 -0
- package/dist/services/scheduler.js +350 -0
- package/dist/services/scheduler.js.map +1 -0
- package/dist/services/secrets.d.ts +31 -0
- package/dist/services/secrets.d.ts.map +1 -0
- package/dist/services/secrets.js +206 -0
- package/dist/services/secrets.js.map +1 -0
- package/dist/services/settings-service.d.ts +132 -0
- package/dist/services/settings-service.d.ts.map +1 -0
- package/dist/services/settings-service.js +378 -0
- package/dist/services/settings-service.js.map +1 -0
- package/dist/services/solution-diff.d.ts +127 -0
- package/dist/services/solution-diff.d.ts.map +1 -0
- package/dist/services/solution-diff.js +260 -0
- package/dist/services/solution-diff.js.map +1 -0
- package/dist/services/solution-mode-detector.d.ts +35 -0
- package/dist/services/solution-mode-detector.d.ts.map +1 -0
- package/dist/services/solution-mode-detector.js +84 -0
- package/dist/services/solution-mode-detector.js.map +1 -0
- package/dist/services/tenant-resolver.d.ts +55 -0
- package/dist/services/tenant-resolver.d.ts.map +1 -0
- package/dist/services/tenant-resolver.js +126 -0
- package/dist/services/tenant-resolver.js.map +1 -0
- package/dist/services/unmanaged-customizations.d.ts +104 -0
- package/dist/services/unmanaged-customizations.d.ts.map +1 -0
- package/dist/services/unmanaged-customizations.js +521 -0
- package/dist/services/unmanaged-customizations.js.map +1 -0
- package/dist/services/url-templater.d.ts +184 -0
- package/dist/services/url-templater.d.ts.map +1 -0
- package/dist/services/url-templater.js +327 -0
- package/dist/services/url-templater.js.map +1 -0
- package/dist/services/version-checker.d.ts +108 -0
- package/dist/services/version-checker.d.ts.map +1 -0
- package/dist/services/version-checker.js +403 -0
- package/dist/services/version-checker.js.map +1 -0
- package/dist/services/waves.d.ts +90 -0
- package/dist/services/waves.d.ts.map +1 -0
- package/dist/services/waves.js +222 -0
- package/dist/services/waves.js.map +1 -0
- package/dist/services/webhook.d.ts +95 -0
- package/dist/services/webhook.d.ts.map +1 -0
- package/dist/services/webhook.js +244 -0
- package/dist/services/webhook.js.map +1 -0
- package/dist/utils/deployment-tools.d.ts +110 -0
- package/dist/utils/deployment-tools.d.ts.map +1 -0
- package/dist/utils/deployment-tools.js +121 -0
- package/dist/utils/deployment-tools.js.map +1 -0
- package/dist/utils/index.d.ts +17 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,260 @@
|
|
|
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 { readFile } from "node:fs/promises";
|
|
17
|
+
import * as crypto from "node:crypto";
|
|
18
|
+
import { SolutionOperations } from "../dataverse/index.js";
|
|
19
|
+
/**
|
|
20
|
+
* Component type codes in Power Platform
|
|
21
|
+
*/
|
|
22
|
+
export const ComponentTypes = {
|
|
23
|
+
1: "Entity",
|
|
24
|
+
2: "Attribute",
|
|
25
|
+
3: "Relationship",
|
|
26
|
+
9: "Option Set",
|
|
27
|
+
10: "Entity Relationship",
|
|
28
|
+
20: "Security Role",
|
|
29
|
+
21: "Privilege",
|
|
30
|
+
26: "View",
|
|
31
|
+
29: "Workflow",
|
|
32
|
+
59: "Saved Query Visualization",
|
|
33
|
+
60: "Form",
|
|
34
|
+
61: "Organization",
|
|
35
|
+
62: "Web Resource",
|
|
36
|
+
63: "Site Map",
|
|
37
|
+
65: "Plugin Assembly",
|
|
38
|
+
70: "Plugin Type",
|
|
39
|
+
90: "SDK Message Processing Step",
|
|
40
|
+
91: "SDK Message Processing Step Image",
|
|
41
|
+
92: "Service Endpoint",
|
|
42
|
+
150: "Duplicate Detection Rule",
|
|
43
|
+
300: "Canvas App",
|
|
44
|
+
371: "Connector",
|
|
45
|
+
372: "Connection Reference",
|
|
46
|
+
380: "Environment Variable Definition",
|
|
47
|
+
381: "Environment Variable Value",
|
|
48
|
+
10029: "AI Model",
|
|
49
|
+
10034: "Bot Component",
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Service for comparing solutions and previewing changes
|
|
53
|
+
*/
|
|
54
|
+
export class SolutionDiffService {
|
|
55
|
+
/**
|
|
56
|
+
* Compare a solution file against what's installed in a target environment
|
|
57
|
+
*/
|
|
58
|
+
async compareSolutions(solutionPath, targetClient) {
|
|
59
|
+
// Parse the solution file to get metadata
|
|
60
|
+
const sourceMetadata = await this.parseSolutionFile(solutionPath);
|
|
61
|
+
if (!sourceMetadata) {
|
|
62
|
+
throw new Error("Failed to parse solution file");
|
|
63
|
+
}
|
|
64
|
+
// Get the installed solution in target environment
|
|
65
|
+
const solutionOps = new SolutionOperations(targetClient);
|
|
66
|
+
const installedSolution = await solutionOps.getSolution(sourceMetadata.uniqueName);
|
|
67
|
+
// If solution doesn't exist in target, it's a new install
|
|
68
|
+
if (!installedSolution) {
|
|
69
|
+
return {
|
|
70
|
+
source: {
|
|
71
|
+
uniqueName: sourceMetadata.uniqueName,
|
|
72
|
+
version: sourceMetadata.version,
|
|
73
|
+
componentCount: sourceMetadata.componentCount || 0,
|
|
74
|
+
},
|
|
75
|
+
target: null,
|
|
76
|
+
summary: {
|
|
77
|
+
added: sourceMetadata.componentCount || 0,
|
|
78
|
+
removed: 0,
|
|
79
|
+
modified: 0,
|
|
80
|
+
unchanged: 0,
|
|
81
|
+
},
|
|
82
|
+
differences: [],
|
|
83
|
+
isUpgrade: false,
|
|
84
|
+
isNewInstall: true,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Get components from installed solution
|
|
88
|
+
const installedComponents = await this.getSolutionComponents(targetClient, installedSolution.solutionid);
|
|
89
|
+
// For a proper diff, we would need to extract components from the zip file
|
|
90
|
+
// This is a simplified version that compares versions and basic info
|
|
91
|
+
const isUpgrade = this.compareVersions(sourceMetadata.version, installedSolution.version) > 0;
|
|
92
|
+
return {
|
|
93
|
+
source: {
|
|
94
|
+
uniqueName: sourceMetadata.uniqueName,
|
|
95
|
+
version: sourceMetadata.version,
|
|
96
|
+
componentCount: sourceMetadata.componentCount || 0,
|
|
97
|
+
},
|
|
98
|
+
target: {
|
|
99
|
+
uniqueName: installedSolution.uniquename,
|
|
100
|
+
version: installedSolution.version,
|
|
101
|
+
componentCount: installedComponents.length,
|
|
102
|
+
},
|
|
103
|
+
summary: {
|
|
104
|
+
added: 0,
|
|
105
|
+
removed: 0,
|
|
106
|
+
modified: 0,
|
|
107
|
+
unchanged: installedComponents.length,
|
|
108
|
+
},
|
|
109
|
+
differences: [],
|
|
110
|
+
isUpgrade,
|
|
111
|
+
isNewInstall: false,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get all components from a solution
|
|
116
|
+
*/
|
|
117
|
+
async getSolutionComponents(client, solutionId) {
|
|
118
|
+
const result = await client.get("/solutioncomponents", {
|
|
119
|
+
$filter: `_solutionid_value eq '${solutionId}'`,
|
|
120
|
+
$select: "solutioncomponentid,componenttype,objectid,rootsolutioncomponentid,ismetadata",
|
|
121
|
+
});
|
|
122
|
+
return result.value;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Parse solution.xml from a solution zip file
|
|
126
|
+
*/
|
|
127
|
+
async parseSolutionFile(solutionPath) {
|
|
128
|
+
try {
|
|
129
|
+
const buffer = await readFile(solutionPath);
|
|
130
|
+
// Solutions are ZIP files - we need to extract solution.xml
|
|
131
|
+
// Using a simple approach: look for the XML content in the buffer
|
|
132
|
+
const content = buffer.toString("utf-8");
|
|
133
|
+
// Extract unique name
|
|
134
|
+
const uniqueNameMatch = content.match(/<UniqueName>([^<]+)<\/UniqueName>/);
|
|
135
|
+
const versionMatch = content.match(/<Version>([^<]+)<\/Version>/);
|
|
136
|
+
const friendlyNameMatch = content.match(/<LocalizedName[^>]*description="([^"]+)"/);
|
|
137
|
+
const managedMatch = content.match(/<Managed>([^<]+)<\/Managed>/);
|
|
138
|
+
if (!uniqueNameMatch || !versionMatch) {
|
|
139
|
+
// Try to use JSZip if available, otherwise return minimal info
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
uniqueName: uniqueNameMatch[1],
|
|
144
|
+
version: versionMatch[1],
|
|
145
|
+
friendlyName: friendlyNameMatch?.[1] || uniqueNameMatch[1],
|
|
146
|
+
isManaged: managedMatch?.[1] === "1" || managedMatch?.[1] === "true",
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Compare two version strings
|
|
155
|
+
* Returns: >0 if v1 > v2, <0 if v1 < v2, 0 if equal
|
|
156
|
+
*/
|
|
157
|
+
compareVersions(v1, v2) {
|
|
158
|
+
const parts1 = v1.split(".").map(Number);
|
|
159
|
+
const parts2 = v2.split(".").map(Number);
|
|
160
|
+
const maxLength = Math.max(parts1.length, parts2.length);
|
|
161
|
+
for (let i = 0; i < maxLength; i++) {
|
|
162
|
+
const p1 = parts1[i] || 0;
|
|
163
|
+
const p2 = parts2[i] || 0;
|
|
164
|
+
if (p1 !== p2) {
|
|
165
|
+
return p1 - p2;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Preview what will happen during deployment
|
|
172
|
+
*/
|
|
173
|
+
async previewDeployment(solutionPath, targetClient) {
|
|
174
|
+
const comparison = await this.compareSolutions(solutionPath, targetClient);
|
|
175
|
+
const warnings = [];
|
|
176
|
+
// Check for potential issues
|
|
177
|
+
if (!comparison.isNewInstall && !comparison.isUpgrade && comparison.target) {
|
|
178
|
+
if (this.compareVersions(comparison.source.version, comparison.target.version) < 0) {
|
|
179
|
+
warnings.push(`Source version (${comparison.source.version}) is older than target (${comparison.target.version}). This may cause issues.`);
|
|
180
|
+
}
|
|
181
|
+
if (comparison.source.version === comparison.target.version) {
|
|
182
|
+
warnings.push(`Same version (${comparison.source.version}) already installed. Import will overwrite existing customizations.`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Estimate duration based on component count
|
|
186
|
+
const componentCount = comparison.source.componentCount;
|
|
187
|
+
const baseDuration = 30000; // 30 seconds base
|
|
188
|
+
const perComponentDuration = 100; // 100ms per component
|
|
189
|
+
const estimatedDurationMs = baseDuration + componentCount * perComponentDuration;
|
|
190
|
+
return {
|
|
191
|
+
willInstall: comparison.isNewInstall,
|
|
192
|
+
willUpgrade: comparison.isUpgrade,
|
|
193
|
+
sourceVersion: comparison.source.version,
|
|
194
|
+
targetVersion: comparison.target?.version || null,
|
|
195
|
+
warnings,
|
|
196
|
+
estimatedDurationMs,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Calculate checksum for a solution file
|
|
201
|
+
*/
|
|
202
|
+
async calculateChecksum(solutionPath) {
|
|
203
|
+
const buffer = await readFile(solutionPath);
|
|
204
|
+
return crypto.createHash("sha256").update(buffer).digest("hex");
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Verify solution file integrity
|
|
208
|
+
*/
|
|
209
|
+
async verifySolutionIntegrity(solutionPath, expectedChecksum) {
|
|
210
|
+
const errors = [];
|
|
211
|
+
let checksum;
|
|
212
|
+
try {
|
|
213
|
+
checksum = await this.calculateChecksum(solutionPath);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
return {
|
|
217
|
+
valid: false,
|
|
218
|
+
checksum: "",
|
|
219
|
+
errors: [
|
|
220
|
+
`Failed to read solution file: ${error instanceof Error ? error.message : String(error)}`,
|
|
221
|
+
],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// Verify checksum if provided
|
|
225
|
+
if (expectedChecksum && checksum !== expectedChecksum) {
|
|
226
|
+
errors.push(`Checksum mismatch: expected ${expectedChecksum}, got ${checksum}`);
|
|
227
|
+
}
|
|
228
|
+
// Try to parse the solution
|
|
229
|
+
const metadata = await this.parseSolutionFile(solutionPath);
|
|
230
|
+
if (!metadata) {
|
|
231
|
+
errors.push("Failed to parse solution metadata from file");
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
valid: errors.length === 0,
|
|
235
|
+
checksum,
|
|
236
|
+
errors,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get summary of solution contents (for display purposes)
|
|
241
|
+
*/
|
|
242
|
+
async getSolutionSummary(solutionPath) {
|
|
243
|
+
try {
|
|
244
|
+
const buffer = await readFile(solutionPath);
|
|
245
|
+
const metadata = await this.parseSolutionFile(solutionPath);
|
|
246
|
+
if (!metadata) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
...metadata,
|
|
251
|
+
checksum: crypto.createHash("sha256").update(buffer).digest("hex"),
|
|
252
|
+
fileSizeBytes: buffer.length,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=solution-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solution-diff.js","sourceRoot":"","sources":["../../src/services/solution-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
export interface SolutionModeCheck {
|
|
17
|
+
managedCount: number;
|
|
18
|
+
unmanagedCount: number;
|
|
19
|
+
notInstalledCount: number;
|
|
20
|
+
hasConflict: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface TargetEnvironment {
|
|
23
|
+
tenantId: string;
|
|
24
|
+
environmentUrl: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check solution installation mode across target environments.
|
|
29
|
+
*
|
|
30
|
+
* Queries each target in parallel and returns counts of managed/unmanaged/not-installed
|
|
31
|
+
* installations. The `hasConflict` flag indicates whether some targets have the solution
|
|
32
|
+
* as managed while others have it as unmanaged.
|
|
33
|
+
*/
|
|
34
|
+
export declare function detectSolutionMode(solutionName: string, targets: TargetEnvironment[], clientId: string, clientSecret: string): Promise<SolutionModeCheck>;
|
|
35
|
+
//# sourceMappingURL=solution-mode-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solution-mode-detector.d.ts","sourceRoot":"","sources":["../../src/services/solution-mode-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAkBH,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,iBAAiB,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAoD5B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
* Solution Mode Detector
|
|
18
|
+
*
|
|
19
|
+
* Detects whether a solution is installed as managed or unmanaged across
|
|
20
|
+
* target environments to help auto-detect the correct export mode.
|
|
21
|
+
*
|
|
22
|
+
* Extracted from CLI deploy.ts to make this reusable and testable.
|
|
23
|
+
*/
|
|
24
|
+
import { DataverseClient } from "../dataverse/client.js";
|
|
25
|
+
import { TokenManager } from "../auth/token-manager.js";
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Service
|
|
28
|
+
// ============================================================================
|
|
29
|
+
/**
|
|
30
|
+
* Check solution installation mode across target environments.
|
|
31
|
+
*
|
|
32
|
+
* Queries each target in parallel and returns counts of managed/unmanaged/not-installed
|
|
33
|
+
* installations. The `hasConflict` flag indicates whether some targets have the solution
|
|
34
|
+
* as managed while others have it as unmanaged.
|
|
35
|
+
*/
|
|
36
|
+
export async function detectSolutionMode(solutionName, targets, clientId, clientSecret) {
|
|
37
|
+
let managedCount = 0;
|
|
38
|
+
let unmanagedCount = 0;
|
|
39
|
+
let notInstalledCount = 0;
|
|
40
|
+
// Check each target in parallel for speed
|
|
41
|
+
const checks = targets.map(async (target) => {
|
|
42
|
+
try {
|
|
43
|
+
const tokenManager = new TokenManager({
|
|
44
|
+
tenantId: target.tenantId,
|
|
45
|
+
clientId,
|
|
46
|
+
clientSecret,
|
|
47
|
+
});
|
|
48
|
+
const client = new DataverseClient({
|
|
49
|
+
environmentUrl: target.environmentUrl,
|
|
50
|
+
tokenManager,
|
|
51
|
+
});
|
|
52
|
+
const result = await client.get("/solutions", {
|
|
53
|
+
$filter: `uniquename eq '${solutionName}'`,
|
|
54
|
+
$select: "solutionid,uniquename,ismanaged",
|
|
55
|
+
});
|
|
56
|
+
if (result.value.length === 0) {
|
|
57
|
+
return "not_installed";
|
|
58
|
+
}
|
|
59
|
+
return result.value[0].ismanaged ? "managed" : "unmanaged";
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// If we can't check, assume not installed (will fail at import if wrong)
|
|
63
|
+
return "not_installed";
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const results = await Promise.all(checks);
|
|
67
|
+
for (const mode of results) {
|
|
68
|
+
if (mode === "managed")
|
|
69
|
+
managedCount++;
|
|
70
|
+
else if (mode === "unmanaged")
|
|
71
|
+
unmanagedCount++;
|
|
72
|
+
else
|
|
73
|
+
notInstalledCount++;
|
|
74
|
+
}
|
|
75
|
+
// Conflict if we have both managed and unmanaged installations
|
|
76
|
+
const hasConflict = managedCount > 0 && unmanagedCount > 0;
|
|
77
|
+
return {
|
|
78
|
+
managedCount,
|
|
79
|
+
unmanagedCount,
|
|
80
|
+
notInstalledCount,
|
|
81
|
+
hasConflict,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=solution-mode-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solution-mode-detector.js","sourceRoot":"","sources":["../../src/services/solution-mode-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAuB,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAmBxD,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB,EACpB,OAA4B,EAC5B,QAAgB,EAChB,YAAoB;IAEpB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAE1B,0CAA0C;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QAC1C,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC;gBACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,QAAQ;gBACR,YAAY;aACb,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;gBACjC,cAAc,EAAE,MAAM,CAAC,cAAc;gBACrC,YAAY;aACb,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAA8B,YAAY,EAAE;gBACzE,OAAO,EAAE,kBAAkB,YAAY,GAAG;gBAC1C,OAAO,EAAE,iCAAiC;aAC3C,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,eAAwB,CAAC;YAClC,CAAC;YAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,SAAmB,CAAC,CAAC,CAAE,WAAqB,CAAC;QACnF,CAAC;QAAC,MAAM,CAAC;YACP,yEAAyE;YACzE,OAAO,eAAwB,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,SAAS;YAAE,YAAY,EAAE,CAAC;aAClC,IAAI,IAAI,KAAK,WAAW;YAAE,cAAc,EAAE,CAAC;;YAC3C,iBAAiB,EAAE,CAAC;IAC3B,CAAC;IAED,+DAA+D;IAC/D,MAAM,WAAW,GAAG,YAAY,GAAG,CAAC,IAAI,cAAc,GAAG,CAAC,CAAC;IAE3D,OAAO;QACL,YAAY;QACZ,cAAc;QACd,iBAAiB;QACjB,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
* Tenant URL Resolver
|
|
18
|
+
*
|
|
19
|
+
* Derives tenant-specific URL values from a tenant's configuration,
|
|
20
|
+
* primarily using the environmentUrl (Dynamics CRM URL) as the source of truth.
|
|
21
|
+
*/
|
|
22
|
+
import { TenantConfig } from "../config/schema.js";
|
|
23
|
+
import { TenantUrlValues } from "./url-templater.js";
|
|
24
|
+
/**
|
|
25
|
+
* Resolve tenant URL values from a TenantConfig
|
|
26
|
+
*
|
|
27
|
+
* Uses the environmentUrl (e.g., https://contoso.crm.dynamics.com) to derive:
|
|
28
|
+
* - tenant: The org/tenant identifier (e.g., "contoso")
|
|
29
|
+
* - sharepoint: SharePoint domain (e.g., "contoso.sharepoint.com")
|
|
30
|
+
* - dynamicsCrm: Dynamics CRM domain (e.g., "contoso.crm.dynamics.com")
|
|
31
|
+
* - onmicrosoft: Default tenant domain (e.g., "contoso.onmicrosoft.com")
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveTenantUrls(tenant: TenantConfig): TenantUrlValues;
|
|
34
|
+
/**
|
|
35
|
+
* Apply manual overrides to resolved tenant URLs
|
|
36
|
+
*/
|
|
37
|
+
export declare function applyUrlOverrides(tenantUrls: TenantUrlValues, overrides?: Partial<TenantUrlValues>): TenantUrlValues;
|
|
38
|
+
/**
|
|
39
|
+
* Validate that all required URL values are present
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateTenantUrls(tenantUrls: TenantUrlValues): {
|
|
42
|
+
valid: boolean;
|
|
43
|
+
missing: string[];
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Get a preview of URL transformations for a tenant
|
|
47
|
+
*/
|
|
48
|
+
export declare function previewUrlTransformations(templates: Array<{
|
|
49
|
+
originalUrl: string;
|
|
50
|
+
templatePattern: string;
|
|
51
|
+
}>, tenantUrls: TenantUrlValues): Array<{
|
|
52
|
+
original: string;
|
|
53
|
+
resolved: string;
|
|
54
|
+
}>;
|
|
55
|
+
//# sourceMappingURL=tenant-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-resolver.d.ts","sourceRoot":"","sources":["../../src/services/tenant-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,CAiDvE;AAgBD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,eAAe,EAC3B,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GACnC,eAAe,CAYjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,eAAe,GAAG;IAC/D,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAYA;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,EAClE,UAAU,EAAE,eAAe,GAC1B,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/C"}
|
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
* Resolve tenant URL values from a TenantConfig
|
|
18
|
+
*
|
|
19
|
+
* Uses the environmentUrl (e.g., https://contoso.crm.dynamics.com) to derive:
|
|
20
|
+
* - tenant: The org/tenant identifier (e.g., "contoso")
|
|
21
|
+
* - sharepoint: SharePoint domain (e.g., "contoso.sharepoint.com")
|
|
22
|
+
* - dynamicsCrm: Dynamics CRM domain (e.g., "contoso.crm.dynamics.com")
|
|
23
|
+
* - onmicrosoft: Default tenant domain (e.g., "contoso.onmicrosoft.com")
|
|
24
|
+
*/
|
|
25
|
+
export function resolveTenantUrls(tenant) {
|
|
26
|
+
try {
|
|
27
|
+
const url = new URL(tenant.environmentUrl);
|
|
28
|
+
const hostname = url.hostname;
|
|
29
|
+
// Try to parse Dynamics CRM URL: {org}.crm{N}.dynamics.com
|
|
30
|
+
const crmMatch = hostname.match(/^([a-zA-Z0-9-]+)\.(crm[0-9]*)\.dynamics\.com$/i);
|
|
31
|
+
if (crmMatch) {
|
|
32
|
+
const orgName = crmMatch[1];
|
|
33
|
+
const region = crmMatch[2];
|
|
34
|
+
return {
|
|
35
|
+
tenant: orgName,
|
|
36
|
+
sharepoint: `${orgName}.sharepoint.com`,
|
|
37
|
+
dynamicsCrm: `${orgName}.${region}.dynamics.com`,
|
|
38
|
+
onmicrosoft: `${orgName}.onmicrosoft.com`,
|
|
39
|
+
region,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Try alternate format: {org}.api.crm{N}.dynamics.com
|
|
43
|
+
const apiMatch = hostname.match(/^([a-zA-Z0-9-]+)\.api\.(crm[0-9]*)\.dynamics\.com$/i);
|
|
44
|
+
if (apiMatch) {
|
|
45
|
+
const orgName = apiMatch[1];
|
|
46
|
+
const region = apiMatch[2];
|
|
47
|
+
return {
|
|
48
|
+
tenant: orgName,
|
|
49
|
+
sharepoint: `${orgName}.sharepoint.com`,
|
|
50
|
+
dynamicsCrm: `${orgName}.${region}.dynamics.com`,
|
|
51
|
+
onmicrosoft: `${orgName}.onmicrosoft.com`,
|
|
52
|
+
region,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Invalid URL, fall through to fallback
|
|
58
|
+
}
|
|
59
|
+
// Fallback: sanitize tenant name to create a valid identifier
|
|
60
|
+
const sanitized = sanitizeTenantName(tenant.name);
|
|
61
|
+
return {
|
|
62
|
+
tenant: sanitized,
|
|
63
|
+
sharepoint: `${sanitized}.sharepoint.com`,
|
|
64
|
+
dynamicsCrm: `${sanitized}.crm.dynamics.com`,
|
|
65
|
+
onmicrosoft: `${sanitized}.onmicrosoft.com`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Sanitize a tenant name to create a valid URL identifier
|
|
70
|
+
*/
|
|
71
|
+
function sanitizeTenantName(name) {
|
|
72
|
+
return (name
|
|
73
|
+
.toLowerCase()
|
|
74
|
+
.replace(/[^a-z0-9-]/g, "") // Remove invalid characters
|
|
75
|
+
.replace(/^-+|-+$/g, "") // Remove leading/trailing dashes
|
|
76
|
+
.substring(0, 63) || // Max subdomain length
|
|
77
|
+
"tenant"); // Fallback if empty
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Apply manual overrides to resolved tenant URLs
|
|
81
|
+
*/
|
|
82
|
+
export function applyUrlOverrides(tenantUrls, overrides) {
|
|
83
|
+
if (!overrides) {
|
|
84
|
+
return tenantUrls;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
tenant: overrides.tenant || tenantUrls.tenant,
|
|
88
|
+
sharepoint: overrides.sharepoint || tenantUrls.sharepoint,
|
|
89
|
+
dynamicsCrm: overrides.dynamicsCrm || tenantUrls.dynamicsCrm,
|
|
90
|
+
onmicrosoft: overrides.onmicrosoft || tenantUrls.onmicrosoft,
|
|
91
|
+
region: overrides.region || tenantUrls.region,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate that all required URL values are present
|
|
96
|
+
*/
|
|
97
|
+
export function validateTenantUrls(tenantUrls) {
|
|
98
|
+
const missing = [];
|
|
99
|
+
if (!tenantUrls.tenant)
|
|
100
|
+
missing.push("tenant");
|
|
101
|
+
if (!tenantUrls.sharepoint)
|
|
102
|
+
missing.push("sharepoint");
|
|
103
|
+
if (!tenantUrls.dynamicsCrm)
|
|
104
|
+
missing.push("dynamicsCrm");
|
|
105
|
+
if (!tenantUrls.onmicrosoft)
|
|
106
|
+
missing.push("onmicrosoft");
|
|
107
|
+
return {
|
|
108
|
+
valid: missing.length === 0,
|
|
109
|
+
missing,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get a preview of URL transformations for a tenant
|
|
114
|
+
*/
|
|
115
|
+
export function previewUrlTransformations(templates, tenantUrls) {
|
|
116
|
+
return templates.map((template) => {
|
|
117
|
+
let resolved = template.templatePattern;
|
|
118
|
+
// Replace {tenant} placeholder
|
|
119
|
+
resolved = resolved.replace(/\{tenant\}/g, tenantUrls.tenant);
|
|
120
|
+
return {
|
|
121
|
+
original: template.originalUrl,
|
|
122
|
+
resolved,
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=tenant-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-resolver.js","sourceRoot":"","sources":["../../src/services/tenant-resolver.ts"],"names":[],"mappings":"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"}
|