@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,205 @@
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 { TokenManager } from "../auth/token-manager.js";
17
+ import { GdapClient } from "../auth/gdap-client.js";
18
+ import { PowerPlatformAdminClient } from "./admin-client.js";
19
+ import { DataverseClient } from "../dataverse/client.js";
20
+ import { POWER_PLATFORM_ADMIN_ROLE_ID } from "../constants.js";
21
+ /**
22
+ * Service for discovering customer tenants and their Power Platform environments
23
+ * via GDAP relationships
24
+ */
25
+ export class TenantDiscoveryService {
26
+ gdapClient;
27
+ partnerConfig;
28
+ // In-memory cache with TTL
29
+ tenantCache = null;
30
+ solutionCache = new Map();
31
+ DEFAULT_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
32
+ constructor(config) {
33
+ this.partnerConfig = config;
34
+ this.gdapClient = new GdapClient(config);
35
+ }
36
+ /**
37
+ * Discover all customer tenants via GDAP and their Power Platform environments
38
+ */
39
+ async discoverTenants(options) {
40
+ const { forceRefresh = false, cacheTtlMs = this.DEFAULT_CACHE_TTL_MS } = options || {};
41
+ // Check cache
42
+ if (!forceRefresh && this.tenantCache && Date.now() < this.tenantCache.expiresAt) {
43
+ return this.tenantCache.data;
44
+ }
45
+ // Get all active GDAP relationships
46
+ const relationships = await this.gdapClient.listDelegatedAdminRelationships();
47
+ // Discover environments for each tenant in parallel
48
+ const discoveries = await Promise.allSettled(relationships.map((rel) => this.discoverTenantEnvironments(rel)));
49
+ const tenants = discoveries.map((result, index) => {
50
+ if (result.status === "fulfilled") {
51
+ return result.value;
52
+ }
53
+ // Return partial info on failure
54
+ const rel = relationships[index];
55
+ return {
56
+ tenantId: rel.customer.tenantId,
57
+ displayName: rel.customer.displayName,
58
+ gdapRelationshipId: rel.id,
59
+ gdapStatus: rel.status,
60
+ gdapEndDateTime: rel.endDateTime,
61
+ hasPowerPlatformAdmin: false,
62
+ environments: [],
63
+ discoveredAt: new Date().toISOString(),
64
+ error: result.reason?.message || "Failed to discover environments",
65
+ };
66
+ });
67
+ // Update cache
68
+ this.tenantCache = {
69
+ data: tenants,
70
+ expiresAt: Date.now() + cacheTtlMs,
71
+ };
72
+ return tenants;
73
+ }
74
+ /**
75
+ * Discover environments for a single tenant
76
+ */
77
+ async discoverTenantEnvironments(relationship) {
78
+ const customerTenantId = relationship.customer.tenantId;
79
+ // Check for Power Platform Admin role
80
+ const powerPlatformAdminRoleId = POWER_PLATFORM_ADMIN_ROLE_ID;
81
+ const hasPowerPlatformAdmin = relationship.accessDetails.unifiedRoles.some((role) => role.roleDefinitionId === powerPlatformAdminRoleId);
82
+ // Create token manager for customer tenant
83
+ const customerTokenManager = new TokenManager({
84
+ ...this.partnerConfig,
85
+ tenantId: customerTenantId,
86
+ });
87
+ // Get environments from Power Platform Admin API
88
+ const adminClient = new PowerPlatformAdminClient({
89
+ tokenManager: customerTokenManager,
90
+ });
91
+ const environments = await adminClient.listEnvironmentSummaries();
92
+ // Find default/production environment
93
+ const defaultEnv = environments.find((e) => e.isDefault) ||
94
+ environments.find((e) => e.type === "Production") ||
95
+ environments[0];
96
+ return {
97
+ tenantId: customerTenantId,
98
+ displayName: relationship.customer.displayName,
99
+ gdapRelationshipId: relationship.id,
100
+ gdapStatus: relationship.status,
101
+ gdapEndDateTime: relationship.endDateTime,
102
+ hasPowerPlatformAdmin,
103
+ environments,
104
+ defaultEnvironment: defaultEnv,
105
+ discoveredAt: new Date().toISOString(),
106
+ };
107
+ }
108
+ /**
109
+ * Discover solutions installed in a tenant's environment
110
+ */
111
+ async discoverSolutions(tenantId, environmentUrl, options) {
112
+ const { forceRefresh = false, cacheTtlMs = this.DEFAULT_CACHE_TTL_MS } = options || {};
113
+ const cacheKey = `${tenantId}:${environmentUrl}`;
114
+ // Check cache
115
+ const cached = this.solutionCache.get(cacheKey);
116
+ if (!forceRefresh && cached && Date.now() < cached.expiresAt) {
117
+ return cached.data;
118
+ }
119
+ // Get tenant info for display name
120
+ const tenants = await this.discoverTenants();
121
+ const tenant = tenants.find((t) => t.tenantId === tenantId);
122
+ const environment = tenant?.environments.find((e) => e.instanceUrl === environmentUrl);
123
+ // Create Dataverse client for the environment
124
+ const customerTokenManager = new TokenManager({
125
+ ...this.partnerConfig,
126
+ tenantId,
127
+ });
128
+ const dataverseClient = new DataverseClient({
129
+ environmentUrl,
130
+ tokenManager: customerTokenManager,
131
+ clientId: this.partnerConfig.clientId,
132
+ });
133
+ // Query solutions
134
+ const solutions = await dataverseClient.querySolutions();
135
+ const discovered = solutions.map((sol) => ({
136
+ tenantId,
137
+ tenantName: tenant?.displayName || tenantId,
138
+ environmentId: environment?.id || "",
139
+ environmentName: environment?.displayName || environmentUrl,
140
+ environmentUrl,
141
+ solutionId: sol.solutionid,
142
+ uniqueName: sol.uniquename,
143
+ friendlyName: sol.friendlyname,
144
+ version: sol.version,
145
+ isManaged: sol.ismanaged,
146
+ publisherName: sol.publisherid?.friendlyname,
147
+ }));
148
+ // Update cache
149
+ this.solutionCache.set(cacheKey, {
150
+ data: discovered,
151
+ expiresAt: Date.now() + cacheTtlMs,
152
+ });
153
+ return discovered;
154
+ }
155
+ /**
156
+ * Discover a specific solution across all tenants
157
+ * Useful for finding where an agent is deployed
158
+ */
159
+ async findSolutionAcrossTenants(solutionUniqueName, options) {
160
+ const { forceRefresh = false } = options || {};
161
+ const tenants = await this.discoverTenants({ forceRefresh });
162
+ const results = [];
163
+ // Check each tenant's default environment
164
+ await Promise.allSettled(tenants
165
+ .filter((t) => t.defaultEnvironment && !t.error)
166
+ .map(async (tenant) => {
167
+ const solutions = await this.discoverSolutions(tenant.tenantId, tenant.defaultEnvironment.instanceUrl, { forceRefresh });
168
+ const match = solutions.find((s) => s.uniqueName === solutionUniqueName);
169
+ if (match) {
170
+ results.push(match);
171
+ }
172
+ }));
173
+ return results;
174
+ }
175
+ /**
176
+ * Get a token manager for a specific customer tenant
177
+ */
178
+ getCustomerTokenManager(customerTenantId) {
179
+ return new TokenManager({
180
+ ...this.partnerConfig,
181
+ tenantId: customerTenantId,
182
+ });
183
+ }
184
+ /**
185
+ * Clear all caches
186
+ */
187
+ clearCache() {
188
+ this.tenantCache = null;
189
+ this.solutionCache.clear();
190
+ }
191
+ /**
192
+ * Clear cache for a specific tenant
193
+ */
194
+ clearTenantCache(tenantId) {
195
+ // Clear solution caches for this tenant
196
+ for (const key of this.solutionCache.keys()) {
197
+ if (key.startsWith(`${tenantId}:`)) {
198
+ this.solutionCache.delete(key);
199
+ }
200
+ }
201
+ // Force refresh of tenant list on next call
202
+ this.tenantCache = null;
203
+ }
204
+ }
205
+ //# sourceMappingURL=tenant-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-discovery.js","sourceRoot":"","sources":["../../src/powerplatform/tenant-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAsB,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,UAAU,EAA8B,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAsB,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AA+C/D;;;GAGG;AACH,MAAM,OAAO,sBAAsB;IACzB,UAAU,CAAa;IACvB,aAAa,CAAwB;IAE7C,2BAA2B;IACnB,WAAW,GAA0C,IAAI,CAAC;IAC1D,aAAa,GAAkD,IAAI,GAAG,EAAE,CAAC;IAEhE,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;IAEjE,YAAY,MAA6B;QACvC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,OAGrB;QACC,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAEvF,cAAc;QACd,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YACjF,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAC/B,CAAC;QAED,oCAAoC;QACpC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,+BAA+B,EAAE,CAAC;QAE9E,oDAAoD;QACpD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,CAC1C,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC,CACjE,CAAC;QAEF,MAAM,OAAO,GAAuB,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACpE,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAClC,OAAO,MAAM,CAAC,KAAK,CAAC;YACtB,CAAC;YAED,iCAAiC;YACjC,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YACjC,OAAO;gBACL,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ;gBAC/B,WAAW,EAAE,GAAG,CAAC,QAAQ,CAAC,WAAW;gBACrC,kBAAkB,EAAE,GAAG,CAAC,EAAE;gBAC1B,UAAU,EAAE,GAAG,CAAC,MAAM;gBACtB,eAAe,EAAE,GAAG,CAAC,WAAW;gBAChC,qBAAqB,EAAE,KAAK;gBAC5B,YAAY,EAAE,EAAE;gBAChB,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,IAAI,iCAAiC;aACnE,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,eAAe;QACf,IAAI,CAAC,WAAW,GAAG;YACjB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU;SACnC,CAAC;QAEF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,0BAA0B,CACtC,YAAwC;QAExC,MAAM,gBAAgB,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAExD,sCAAsC;QACtC,MAAM,wBAAwB,GAAG,4BAA4B,CAAC;QAC9D,MAAM,qBAAqB,GAAG,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,CACxE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,KAAK,wBAAwB,CAC7D,CAAC;QAEF,2CAA2C;QAC3C,MAAM,oBAAoB,GAAG,IAAI,YAAY,CAAC;YAC5C,GAAG,IAAI,CAAC,aAAa;YACrB,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;QAEH,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAI,wBAAwB,CAAC;YAC/C,YAAY,EAAE,oBAAoB;SACnC,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,wBAAwB,EAAE,CAAC;QAElE,sCAAsC;QACtC,MAAM,UAAU,GACd,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YACrC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC;YACjD,YAAY,CAAC,CAAC,CAAC,CAAC;QAElB,OAAO;YACL,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,YAAY,CAAC,QAAQ,CAAC,WAAW;YAC9C,kBAAkB,EAAE,YAAY,CAAC,EAAE;YACnC,UAAU,EAAE,YAAY,CAAC,MAAM;YAC/B,eAAe,EAAE,YAAY,CAAC,WAAW;YACzC,qBAAqB;YACrB,YAAY;YACZ,kBAAkB,EAAE,UAAU;YAC9B,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACvC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CACrB,QAAgB,EAChB,cAAsB,EACtB,OAGC;QAED,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC,oBAAoB,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QACvF,MAAM,QAAQ,GAAG,GAAG,QAAQ,IAAI,cAAc,EAAE,CAAC;QAEjD,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,CAAC,YAAY,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YAC7D,OAAO,MAAM,CAAC,IAAI,CAAC;QACrB,CAAC;QAED,mCAAmC;QACnC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAC5D,MAAM,WAAW,GAAG,MAAM,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,cAAc,CAAC,CAAC;QAEvF,8CAA8C;QAC9C,MAAM,oBAAoB,GAAG,IAAI,YAAY,CAAC;YAC5C,GAAG,IAAI,CAAC,aAAa;YACrB,QAAQ;SACT,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;YAC1C,cAAc;YACd,YAAY,EAAE,oBAAoB;YAClC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ;SACtC,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,cAAc,EAAE,CAAC;QAEzD,MAAM,UAAU,GAAyB,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/D,QAAQ;YACR,UAAU,EAAE,MAAM,EAAE,WAAW,IAAI,QAAQ;YAC3C,aAAa,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE;YACpC,eAAe,EAAE,WAAW,EAAE,WAAW,IAAI,cAAc;YAC3D,cAAc;YACd,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,aAAa,EAAE,GAAG,CAAC,WAAW,EAAE,YAAY;SAC7C,CAAC,CAAC,CAAC;QAEJ,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE;YAC/B,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU;SACnC,CAAC,CAAC;QAEH,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB,CAC7B,kBAA0B,EAC1B,OAEC;QAED,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAE/C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAyB,EAAE,CAAC;QAEzC,0CAA0C;QAC1C,MAAM,OAAO,CAAC,UAAU,CACtB,OAAO;aACJ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;aAC/C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACpB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAC5C,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,kBAAmB,CAAC,WAAW,EACtC,EAAE,YAAY,EAAE,CACjB,CAAC;YAEF,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,kBAAkB,CAAC,CAAC;YACzE,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CACL,CAAC;QAEF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,uBAAuB,CAAC,gBAAwB;QAC9C,OAAO,IAAI,YAAY,CAAC;YACtB,GAAG,IAAI,CAAC,aAAa;YACrB,QAAQ,EAAE,gBAAgB;SAC3B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,QAAgB;QAC/B,wCAAwC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QACD,4CAA4C;QAC5C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,41 @@
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 type { TenantConfig } from "../config/schema.js";
17
+ import type { DemoPreconditionState } from "../mock/demo-data.js";
18
+ import type { ComparisonOp, Precondition, PreconditionFailure, PreconditionManifest } from "./types.js";
19
+ /**
20
+ * Resolver contract: given a tenant + precondition, return the synthetic
21
+ * (Phase 1) or live (Phase 2) state of the matched resource — or the literal
22
+ * `"missing-resource"` when nothing in the tenant matches the precondition's
23
+ * `matcher`. Absence is itself a finding, not an error.
24
+ */
25
+ export type PreconditionStateResolver = (tenant: TenantConfig, precondition: Precondition) => DemoPreconditionState | "missing-resource";
26
+ /**
27
+ * Apply a `ComparisonOp` between the actual property value and the
28
+ * requirement's required value. Returns true when the requirement is
29
+ * satisfied.
30
+ */
31
+ export declare function evaluateOp(op: ComparisonOp, current: unknown, required: unknown): boolean;
32
+ /**
33
+ * Check every (tenant × precondition) pair against the supplied state
34
+ * resolver and emit one `PreconditionFailure` per failed requirement.
35
+ *
36
+ * Phase 1 callers wire `resolveState` to a synthetic lookup against
37
+ * `DEMO_TENANTS[].metadata.preconditionState`. Phase 2 will swap that for
38
+ * a live Microsoft Graph TCM client; the rest of this function stays put.
39
+ */
40
+ export declare function checkPreconditions(manifest: PreconditionManifest, tenants: TenantConfig[], resolveState: PreconditionStateResolver): PreconditionFailure[];
41
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/preconditions/check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,YAAY,KACvB,qBAAqB,GAAG,kBAAkB,CAAC;AAkDhD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CA+BzF;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,yBAAyB,GACtC,mBAAmB,EAAE,CA2DvB"}
@@ -0,0 +1,173 @@
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
+ * Walk a dot-path within an object. Returns `undefined` for any segment
18
+ * that's not a plain object on the path. Used to resolve a requirement's
19
+ * `property` against the resource's `currentProperties`.
20
+ */
21
+ function getByDotPath(obj, path) {
22
+ const parts = path.split(".");
23
+ let current = obj;
24
+ for (const part of parts) {
25
+ if (current === null || current === undefined)
26
+ return undefined;
27
+ if (typeof current !== "object")
28
+ return undefined;
29
+ current = current[part];
30
+ }
31
+ return current;
32
+ }
33
+ /**
34
+ * Strict deep equality. Mirrors Node's util.isDeepStrictEqual semantics for
35
+ * the JSON-shaped values we expect from YAML manifests + synthetic state.
36
+ */
37
+ function deepEqual(a, b) {
38
+ if (Object.is(a, b))
39
+ return true;
40
+ if (typeof a !== typeof b)
41
+ return false;
42
+ if (a === null || b === null)
43
+ return false;
44
+ if (typeof a !== "object")
45
+ return false;
46
+ if (Array.isArray(a)) {
47
+ if (!Array.isArray(b))
48
+ return false;
49
+ if (a.length !== b.length)
50
+ return false;
51
+ for (let i = 0; i < a.length; i++) {
52
+ if (!deepEqual(a[i], b[i]))
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ if (Array.isArray(b))
58
+ return false;
59
+ const aObj = a;
60
+ const bObj = b;
61
+ const aKeys = Object.keys(aObj);
62
+ const bKeys = Object.keys(bObj);
63
+ if (aKeys.length !== bKeys.length)
64
+ return false;
65
+ for (const key of aKeys) {
66
+ if (!Object.prototype.hasOwnProperty.call(bObj, key))
67
+ return false;
68
+ if (!deepEqual(aObj[key], bObj[key]))
69
+ return false;
70
+ }
71
+ return true;
72
+ }
73
+ /**
74
+ * Apply a `ComparisonOp` between the actual property value and the
75
+ * requirement's required value. Returns true when the requirement is
76
+ * satisfied.
77
+ */
78
+ export function evaluateOp(op, current, required) {
79
+ switch (op) {
80
+ case "equals":
81
+ return deepEqual(current, required);
82
+ case "not-equals":
83
+ return !deepEqual(current, required);
84
+ case "at-least": {
85
+ // booleans: true >= true|false, false satisfies only false.
86
+ if (typeof current === "boolean" && typeof required === "boolean") {
87
+ return Number(current) >= Number(required);
88
+ }
89
+ // numbers: standard >=.
90
+ if (typeof current === "number" && typeof required === "number") {
91
+ return current >= required;
92
+ }
93
+ // arrays: current ⊇ required (every required element appears in current).
94
+ if (Array.isArray(current) && Array.isArray(required)) {
95
+ return required.every((v) => current.some((c) => deepEqual(c, v)));
96
+ }
97
+ // mismatched / unsupported types → not satisfied.
98
+ return false;
99
+ }
100
+ case "includes": {
101
+ if (!Array.isArray(current))
102
+ return false;
103
+ return current.some((c) => deepEqual(c, required));
104
+ }
105
+ case "subset-of": {
106
+ if (!Array.isArray(current) || !Array.isArray(required))
107
+ return false;
108
+ return current.every((c) => required.some((r) => deepEqual(r, c)));
109
+ }
110
+ }
111
+ }
112
+ /**
113
+ * Check every (tenant × precondition) pair against the supplied state
114
+ * resolver and emit one `PreconditionFailure` per failed requirement.
115
+ *
116
+ * Phase 1 callers wire `resolveState` to a synthetic lookup against
117
+ * `DEMO_TENANTS[].metadata.preconditionState`. Phase 2 will swap that for
118
+ * a live Microsoft Graph TCM client; the rest of this function stays put.
119
+ */
120
+ export function checkPreconditions(manifest, tenants, resolveState) {
121
+ const failures = [];
122
+ for (const tenant of tenants) {
123
+ for (const precondition of manifest.preconditions) {
124
+ const state = resolveState(tenant, precondition);
125
+ if (state === "missing-resource") {
126
+ // Render the matcher as a human-readable required-value so the user
127
+ // sees what we were looking for (e.g. {displayName: "Require MFA..."}).
128
+ failures.push({
129
+ tenantId: tenant.tenantId,
130
+ tenantName: tenant.name,
131
+ preconditionId: precondition.id,
132
+ description: precondition.description,
133
+ resourceType: precondition.resourceType,
134
+ resourceDisplayName: precondition.matcher.displayName ?? Object.values(precondition.matcher)[0] ?? "(none)",
135
+ resourceId: "",
136
+ failedProperty: "<resource not present>",
137
+ currentValue: undefined,
138
+ requiredValue: precondition.matcher,
139
+ comparisonOp: "equals",
140
+ severity: precondition.severity,
141
+ remediation: precondition.remediation,
142
+ });
143
+ continue;
144
+ }
145
+ // Pull the resource id once for substitution into remediation templates.
146
+ const resourceId = typeof state.currentProperties.id === "string" ? state.currentProperties.id : "";
147
+ // Walk every requirement and emit one failure per mismatch — operators
148
+ // explicitly want each line surfaced rather than collapsed.
149
+ for (const requirement of precondition.requirements) {
150
+ const current = getByDotPath(state.currentProperties, requirement.property);
151
+ if (evaluateOp(requirement.op, current, requirement.value))
152
+ continue;
153
+ failures.push({
154
+ tenantId: tenant.tenantId,
155
+ tenantName: tenant.name,
156
+ preconditionId: precondition.id,
157
+ description: precondition.description,
158
+ resourceType: precondition.resourceType,
159
+ resourceDisplayName: state.resourceDisplayName,
160
+ resourceId,
161
+ failedProperty: requirement.property,
162
+ currentValue: current,
163
+ requiredValue: requirement.value,
164
+ comparisonOp: requirement.op,
165
+ severity: precondition.severity,
166
+ remediation: precondition.remediation,
167
+ });
168
+ }
169
+ }
170
+ }
171
+ return failures;
172
+ }
173
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/preconditions/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
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 * from "./types.js";
17
+ export * from "./schema.js";
18
+ export * from "./loader.js";
19
+ export * from "./check.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preconditions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,20 @@
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 * from "./types.js";
17
+ export * from "./schema.js";
18
+ export * from "./loader.js";
19
+ export * from "./check.js";
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/preconditions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,33 @@
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 type { PreconditionManifest } from "./types.js";
17
+ /**
18
+ * Strip a `.zip` extension and any leading directory from the user's
19
+ * `--solution` arg so we can match the manifest by the solution's logical
20
+ * name. e.g. `./agent packages/CustomerServiceAgent.zip` → `CustomerServiceAgent`.
21
+ */
22
+ export declare function normalizeSolutionName(input: string): string;
23
+ /**
24
+ * Look for `<solutionName>.preconditions.yaml` (or `.yml`) in each search dir
25
+ * and return the first parsed + validated manifest.
26
+ *
27
+ * - Returns `null` when no manifest exists in any search dir. Callers should
28
+ * treat this as "preflight skipped, deploy proceeds, log a visible note."
29
+ * - Throws `PreconditionManifestValidationError` when a manifest IS present
30
+ * but fails schema validation. Better to fail loudly than silently skip.
31
+ */
32
+ export declare function loadPreconditionManifest(solutionName: string, searchDirs: string[]): Promise<PreconditionManifest | null>;
33
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/preconditions/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAyBtC"}
@@ -0,0 +1,65 @@
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 { existsSync } from "node:fs";
18
+ import { join, basename, extname } from "node:path";
19
+ import { parse as parseYaml } from "yaml";
20
+ import { PreconditionManifestSchema, PreconditionManifestValidationError } from "./schema.js";
21
+ /**
22
+ * Strip a `.zip` extension and any leading directory from the user's
23
+ * `--solution` arg so we can match the manifest by the solution's logical
24
+ * name. e.g. `./agent packages/CustomerServiceAgent.zip` → `CustomerServiceAgent`.
25
+ */
26
+ export function normalizeSolutionName(input) {
27
+ const base = basename(input);
28
+ const ext = extname(base);
29
+ return ext.toLowerCase() === ".zip" ? base.slice(0, -ext.length) : base;
30
+ }
31
+ /**
32
+ * Look for `<solutionName>.preconditions.yaml` (or `.yml`) in each search dir
33
+ * and return the first parsed + validated manifest.
34
+ *
35
+ * - Returns `null` when no manifest exists in any search dir. Callers should
36
+ * treat this as "preflight skipped, deploy proceeds, log a visible note."
37
+ * - Throws `PreconditionManifestValidationError` when a manifest IS present
38
+ * but fails schema validation. Better to fail loudly than silently skip.
39
+ */
40
+ export async function loadPreconditionManifest(solutionName, searchDirs) {
41
+ const normalized = normalizeSolutionName(solutionName);
42
+ const candidates = [];
43
+ for (const dir of searchDirs) {
44
+ candidates.push(join(dir, `${normalized}.preconditions.yaml`));
45
+ candidates.push(join(dir, `${normalized}.preconditions.yml`));
46
+ }
47
+ const found = candidates.find((path) => existsSync(path));
48
+ if (!found)
49
+ return null;
50
+ let raw;
51
+ try {
52
+ const content = await readFile(found, "utf-8");
53
+ raw = parseYaml(content);
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ throw new Error(`Failed to read precondition manifest at ${found}: ${message}`);
58
+ }
59
+ const result = PreconditionManifestSchema.safeParse(raw);
60
+ if (!result.success) {
61
+ throw new PreconditionManifestValidationError(found, result.error.issues);
62
+ }
63
+ return result.data;
64
+ }
65
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/preconditions/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,0BAA0B,EAAE,mCAAmC,EAAE,MAAM,aAAa,CAAC;AAG9F;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,YAAoB,EACpB,UAAoB;IAEpB,MAAM,UAAU,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;IACvD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,qBAAqB,CAAC,CAAC,CAAC;QAC/D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,oBAAoB,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,2CAA2C,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,MAAM,GAAG,0BAA0B,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,mCAAmC,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}