@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.
Files changed (226) hide show
  1. package/LICENSE +198 -0
  2. package/dist/auth/device-code-login.d.ts +40 -0
  3. package/dist/auth/device-code-login.d.ts.map +1 -0
  4. package/dist/auth/device-code-login.js +59 -0
  5. package/dist/auth/device-code-login.js.map +1 -0
  6. package/dist/auth/gdap-client.d.ts +81 -0
  7. package/dist/auth/gdap-client.d.ts.map +1 -0
  8. package/dist/auth/gdap-client.js +128 -0
  9. package/dist/auth/gdap-client.js.map +1 -0
  10. package/dist/auth/index.d.ts +19 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +19 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/token-manager.d.ts +54 -0
  15. package/dist/auth/token-manager.d.ts.map +1 -0
  16. package/dist/auth/token-manager.js +150 -0
  17. package/dist/auth/token-manager.js.map +1 -0
  18. package/dist/client.d.ts +27 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +27 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/config/client.d.ts +24 -0
  23. package/dist/config/client.d.ts.map +1 -0
  24. package/dist/config/client.js +18 -0
  25. package/dist/config/client.js.map +1 -0
  26. package/dist/config/index.d.ts +18 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +18 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/config/loader.d.ts +81 -0
  31. package/dist/config/loader.d.ts.map +1 -0
  32. package/dist/config/loader.js +271 -0
  33. package/dist/config/loader.js.map +1 -0
  34. package/dist/config/schema.d.ts +751 -0
  35. package/dist/config/schema.d.ts.map +1 -0
  36. package/dist/config/schema.js +556 -0
  37. package/dist/config/schema.js.map +1 -0
  38. package/dist/constants.d.ts +116 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +170 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/dataverse/agent-resolver.d.ts +98 -0
  43. package/dist/dataverse/agent-resolver.d.ts.map +1 -0
  44. package/dist/dataverse/agent-resolver.js +185 -0
  45. package/dist/dataverse/agent-resolver.js.map +1 -0
  46. package/dist/dataverse/client.d.ts +104 -0
  47. package/dist/dataverse/client.d.ts.map +1 -0
  48. package/dist/dataverse/client.js +272 -0
  49. package/dist/dataverse/client.js.map +1 -0
  50. package/dist/dataverse/connection-refs.d.ts +115 -0
  51. package/dist/dataverse/connection-refs.d.ts.map +1 -0
  52. package/dist/dataverse/connection-refs.js +203 -0
  53. package/dist/dataverse/connection-refs.js.map +1 -0
  54. package/dist/dataverse/index.d.ts +20 -0
  55. package/dist/dataverse/index.d.ts.map +1 -0
  56. package/dist/dataverse/index.js +20 -0
  57. package/dist/dataverse/index.js.map +1 -0
  58. package/dist/dataverse/solution-ops.d.ts +100 -0
  59. package/dist/dataverse/solution-ops.d.ts.map +1 -0
  60. package/dist/dataverse/solution-ops.js +288 -0
  61. package/dist/dataverse/solution-ops.js.map +1 -0
  62. package/dist/errors.d.ts +171 -0
  63. package/dist/errors.d.ts.map +1 -0
  64. package/dist/errors.js +178 -0
  65. package/dist/errors.js.map +1 -0
  66. package/dist/index.d.ts +27 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +40 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/mock/demo-data.d.ts +213 -0
  71. package/dist/mock/demo-data.d.ts.map +1 -0
  72. package/dist/mock/demo-data.js +1096 -0
  73. package/dist/mock/demo-data.js.map +1 -0
  74. package/dist/mock/demo-deployment-store.d.ts +77 -0
  75. package/dist/mock/demo-deployment-store.d.ts.map +1 -0
  76. package/dist/mock/demo-deployment-store.js +85 -0
  77. package/dist/mock/demo-deployment-store.js.map +1 -0
  78. package/dist/powerplatform/admin-client.d.ts +226 -0
  79. package/dist/powerplatform/admin-client.d.ts.map +1 -0
  80. package/dist/powerplatform/admin-client.js +315 -0
  81. package/dist/powerplatform/admin-client.js.map +1 -0
  82. package/dist/powerplatform/index.d.ts +18 -0
  83. package/dist/powerplatform/index.d.ts.map +1 -0
  84. package/dist/powerplatform/index.js +18 -0
  85. package/dist/powerplatform/index.js.map +1 -0
  86. package/dist/powerplatform/tenant-discovery.d.ts +100 -0
  87. package/dist/powerplatform/tenant-discovery.d.ts.map +1 -0
  88. package/dist/powerplatform/tenant-discovery.js +205 -0
  89. package/dist/powerplatform/tenant-discovery.js.map +1 -0
  90. package/dist/preconditions/check.d.ts +41 -0
  91. package/dist/preconditions/check.d.ts.map +1 -0
  92. package/dist/preconditions/check.js +173 -0
  93. package/dist/preconditions/check.js.map +1 -0
  94. package/dist/preconditions/index.d.ts +20 -0
  95. package/dist/preconditions/index.d.ts.map +1 -0
  96. package/dist/preconditions/index.js +20 -0
  97. package/dist/preconditions/index.js.map +1 -0
  98. package/dist/preconditions/loader.d.ts +33 -0
  99. package/dist/preconditions/loader.d.ts.map +1 -0
  100. package/dist/preconditions/loader.js +65 -0
  101. package/dist/preconditions/loader.js.map +1 -0
  102. package/dist/preconditions/schema.d.ts +103 -0
  103. package/dist/preconditions/schema.d.ts.map +1 -0
  104. package/dist/preconditions/schema.js +93 -0
  105. package/dist/preconditions/schema.js.map +1 -0
  106. package/dist/preconditions/types.d.ts +118 -0
  107. package/dist/preconditions/types.d.ts.map +1 -0
  108. package/dist/preconditions/types.js +17 -0
  109. package/dist/preconditions/types.js.map +1 -0
  110. package/dist/queue/index.d.ts +17 -0
  111. package/dist/queue/index.d.ts.map +1 -0
  112. package/dist/queue/index.js +17 -0
  113. package/dist/queue/index.js.map +1 -0
  114. package/dist/queue/memory-queue.d.ts +86 -0
  115. package/dist/queue/memory-queue.d.ts.map +1 -0
  116. package/dist/queue/memory-queue.js +221 -0
  117. package/dist/queue/memory-queue.js.map +1 -0
  118. package/dist/services/audit-log.d.ts +59 -0
  119. package/dist/services/audit-log.d.ts.map +1 -0
  120. package/dist/services/audit-log.js +193 -0
  121. package/dist/services/audit-log.js.map +1 -0
  122. package/dist/services/auth-error-parser.d.ts +36 -0
  123. package/dist/services/auth-error-parser.d.ts.map +1 -0
  124. package/dist/services/auth-error-parser.js +90 -0
  125. package/dist/services/auth-error-parser.js.map +1 -0
  126. package/dist/services/deployment-doctor.d.ts +109 -0
  127. package/dist/services/deployment-doctor.d.ts.map +1 -0
  128. package/dist/services/deployment-doctor.js +476 -0
  129. package/dist/services/deployment-doctor.js.map +1 -0
  130. package/dist/services/deployment-notifications.d.ts +41 -0
  131. package/dist/services/deployment-notifications.d.ts.map +1 -0
  132. package/dist/services/deployment-notifications.js +161 -0
  133. package/dist/services/deployment-notifications.js.map +1 -0
  134. package/dist/services/deployment-progress.d.ts +89 -0
  135. package/dist/services/deployment-progress.d.ts.map +1 -0
  136. package/dist/services/deployment-progress.js +244 -0
  137. package/dist/services/deployment-progress.js.map +1 -0
  138. package/dist/services/deployment-service.d.ts +97 -0
  139. package/dist/services/deployment-service.d.ts.map +1 -0
  140. package/dist/services/deployment-service.js +375 -0
  141. package/dist/services/deployment-service.js.map +1 -0
  142. package/dist/services/drift-analyzer.d.ts +86 -0
  143. package/dist/services/drift-analyzer.d.ts.map +1 -0
  144. package/dist/services/drift-analyzer.js +273 -0
  145. package/dist/services/drift-analyzer.js.map +1 -0
  146. package/dist/services/environment-setup.d.ts +97 -0
  147. package/dist/services/environment-setup.d.ts.map +1 -0
  148. package/dist/services/environment-setup.js +250 -0
  149. package/dist/services/environment-setup.js.map +1 -0
  150. package/dist/services/health-check.d.ts +168 -0
  151. package/dist/services/health-check.d.ts.map +1 -0
  152. package/dist/services/health-check.js +705 -0
  153. package/dist/services/health-check.js.map +1 -0
  154. package/dist/services/index.d.ts +39 -0
  155. package/dist/services/index.d.ts.map +1 -0
  156. package/dist/services/index.js +39 -0
  157. package/dist/services/index.js.map +1 -0
  158. package/dist/services/logger.d.ts +139 -0
  159. package/dist/services/logger.d.ts.map +1 -0
  160. package/dist/services/logger.js +268 -0
  161. package/dist/services/logger.js.map +1 -0
  162. package/dist/services/notification-service.d.ts +55 -0
  163. package/dist/services/notification-service.d.ts.map +1 -0
  164. package/dist/services/notification-service.js +184 -0
  165. package/dist/services/notification-service.js.map +1 -0
  166. package/dist/services/risk-analyzer.d.ts +252 -0
  167. package/dist/services/risk-analyzer.d.ts.map +1 -0
  168. package/dist/services/risk-analyzer.js +866 -0
  169. package/dist/services/risk-analyzer.js.map +1 -0
  170. package/dist/services/rollback.d.ts +57 -0
  171. package/dist/services/rollback.d.ts.map +1 -0
  172. package/dist/services/rollback.js +270 -0
  173. package/dist/services/rollback.js.map +1 -0
  174. package/dist/services/scheduler.d.ts +80 -0
  175. package/dist/services/scheduler.d.ts.map +1 -0
  176. package/dist/services/scheduler.js +350 -0
  177. package/dist/services/scheduler.js.map +1 -0
  178. package/dist/services/secrets.d.ts +31 -0
  179. package/dist/services/secrets.d.ts.map +1 -0
  180. package/dist/services/secrets.js +206 -0
  181. package/dist/services/secrets.js.map +1 -0
  182. package/dist/services/settings-service.d.ts +132 -0
  183. package/dist/services/settings-service.d.ts.map +1 -0
  184. package/dist/services/settings-service.js +378 -0
  185. package/dist/services/settings-service.js.map +1 -0
  186. package/dist/services/solution-diff.d.ts +127 -0
  187. package/dist/services/solution-diff.d.ts.map +1 -0
  188. package/dist/services/solution-diff.js +260 -0
  189. package/dist/services/solution-diff.js.map +1 -0
  190. package/dist/services/solution-mode-detector.d.ts +35 -0
  191. package/dist/services/solution-mode-detector.d.ts.map +1 -0
  192. package/dist/services/solution-mode-detector.js +84 -0
  193. package/dist/services/solution-mode-detector.js.map +1 -0
  194. package/dist/services/tenant-resolver.d.ts +55 -0
  195. package/dist/services/tenant-resolver.d.ts.map +1 -0
  196. package/dist/services/tenant-resolver.js +126 -0
  197. package/dist/services/tenant-resolver.js.map +1 -0
  198. package/dist/services/unmanaged-customizations.d.ts +104 -0
  199. package/dist/services/unmanaged-customizations.d.ts.map +1 -0
  200. package/dist/services/unmanaged-customizations.js +521 -0
  201. package/dist/services/unmanaged-customizations.js.map +1 -0
  202. package/dist/services/url-templater.d.ts +184 -0
  203. package/dist/services/url-templater.d.ts.map +1 -0
  204. package/dist/services/url-templater.js +327 -0
  205. package/dist/services/url-templater.js.map +1 -0
  206. package/dist/services/version-checker.d.ts +108 -0
  207. package/dist/services/version-checker.d.ts.map +1 -0
  208. package/dist/services/version-checker.js +403 -0
  209. package/dist/services/version-checker.js.map +1 -0
  210. package/dist/services/waves.d.ts +90 -0
  211. package/dist/services/waves.d.ts.map +1 -0
  212. package/dist/services/waves.js +222 -0
  213. package/dist/services/waves.js.map +1 -0
  214. package/dist/services/webhook.d.ts +95 -0
  215. package/dist/services/webhook.d.ts.map +1 -0
  216. package/dist/services/webhook.js +244 -0
  217. package/dist/services/webhook.js.map +1 -0
  218. package/dist/utils/deployment-tools.d.ts +110 -0
  219. package/dist/utils/deployment-tools.d.ts.map +1 -0
  220. package/dist/utils/deployment-tools.js +121 -0
  221. package/dist/utils/deployment-tools.js.map +1 -0
  222. package/dist/utils/index.d.ts +17 -0
  223. package/dist/utils/index.d.ts.map +1 -0
  224. package/dist/utils/index.js +18 -0
  225. package/dist/utils/index.js.map +1 -0
  226. 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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"}