@pacaf/wizard-ux 3.4.1 → 3.4.3
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/dist/index.html
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
}
|
|
29
29
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
30
30
|
</style>
|
|
31
|
-
<script type="module" crossorigin src="/assets/index-
|
|
31
|
+
<script type="module" crossorigin src="/assets/index-DJRPvUY4.js"></script>
|
|
32
32
|
</head>
|
|
33
33
|
<body>
|
|
34
34
|
<div id="root"><div id="boot"><div class="ring"></div></div></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pacaf/wizard-ux",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Browser-based setup wizard for Power Apps Code Apps (parallel to @pacaf/wizard CLI).",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"react-dom": "^19.0.0",
|
|
39
39
|
"react-resizable-panels": "^2.1.7",
|
|
40
40
|
"react-router-dom": "^7.1.0",
|
|
41
|
-
"@pacaf/wizard": "3.4.
|
|
41
|
+
"@pacaf/wizard": "3.4.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "^19.0.0",
|
|
@@ -11,7 +11,6 @@ const PACKAGE_DIR = resolve(__dirname, '..', '..', '..');
|
|
|
11
11
|
const PROJECT_DIR = process.cwd();
|
|
12
12
|
const SHELL = await import(pathToFileURL(resolve(PACKAGE_DIR, 'wizard', 'lib', 'shell.mjs')).href);
|
|
13
13
|
const PAC_TARGET = await import(pathToFileURL(resolve(PACKAGE_DIR, 'wizard', 'lib', 'pac-target.mjs')).href);
|
|
14
|
-
const SOLUTION_MEMBERSHIP = await import(pathToFileURL(resolve(PACKAGE_DIR, 'wizard', 'lib', 'solution-membership.mjs')).href);
|
|
15
14
|
|
|
16
15
|
function hasCommand(name) {
|
|
17
16
|
try {
|
|
@@ -107,40 +106,11 @@ function verifyUserProfile(pac, projectDir, state, credentialValues) {
|
|
|
107
106
|
|
|
108
107
|
// Ensure the deployed Code App is a component of the selected solution.
|
|
109
108
|
//
|
|
110
|
-
// `pac code push -s <UNIQUE name>`
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
// is ignored
|
|
115
|
-
// user to delete + recreate. That is wrong: appId === canvasappid, so the
|
|
116
|
-
// app can be added to the solution after the fact.
|
|
117
|
-
//
|
|
118
|
-
// READ + REPAIR (auth-agnostic, via the shared lib):
|
|
119
|
-
// • READ — `pac org fetch` on solutioncomponent (componenttype 300) under
|
|
120
|
-
// the active profile (user OR SPN), so no client secret is needed.
|
|
121
|
-
// • REPAIR — `pac solution add-solution-component --component <appId>
|
|
122
|
-
// --componentType 300 --solutionUniqueName <name>` when absent.
|
|
123
|
-
// The old `pac solution export --managed false` + type-300 count read was
|
|
124
|
-
// malformed and produced false negatives; the old `pac solution list` check
|
|
125
|
-
// was a false positive (it only proved the solution exists). Both are gone.
|
|
126
|
-
async function ensureAppInSolution(log, pac, projectDir, appId, solutionUniqueName, { appDisplayName } = {}) {
|
|
127
|
-
if (!solutionUniqueName) return { status: 'unknown' };
|
|
128
|
-
if (!appId) {
|
|
129
|
-
log.warn(`No appId found in power.config.json — cannot confirm membership in "${solutionUniqueName}". Verify in the Maker Portal.`);
|
|
130
|
-
return { status: 'unknown' };
|
|
131
|
-
}
|
|
132
|
-
log.info(`Confirming the app is in solution "${solutionUniqueName}" (and adding it if missing)...`);
|
|
133
|
-
const runCapture = (file, args, opts) => runFileCapture(log, file, args, opts);
|
|
134
|
-
const result = await SOLUTION_MEMBERSHIP.ensureAppInSolution({
|
|
135
|
-
pac, projectDir, appId, solutionUniqueName, runCapture, log,
|
|
136
|
-
});
|
|
137
|
-
if (result.status !== 'member' && result.status === 'absent') {
|
|
138
|
-
for (const line of SOLUTION_MEMBERSHIP.manualSolutionAddSteps(solutionUniqueName, appDisplayName || 'this Code App', appId)) {
|
|
139
|
-
log.warn(line);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
109
|
+
// The first `pac code push -s <UNIQUE name>` (the CREATE) both creates the
|
|
110
|
+
// canvasapp record AND makes it a component of the chosen solution in one shot
|
|
111
|
+
// — the documented golden path. We REFUSE a bare push below, so the app can
|
|
112
|
+
// never be created OUTSIDE its solution (a silent failure a later -s re-push,
|
|
113
|
+
// which is an ignored UPDATE, cannot fix). No post-push repair is needed (#81).
|
|
144
114
|
|
|
145
115
|
export default {
|
|
146
116
|
meta: {
|
|
@@ -207,7 +177,6 @@ export default {
|
|
|
207
177
|
// the solution — association only happens on the first push WITH the unique
|
|
208
178
|
// name, and a later -s re-push cannot fix it (issue #81).
|
|
209
179
|
const solutionUniqueName = String(state.SOLUTION_UNIQUE_NAME || '').trim();
|
|
210
|
-
const appDisplayName = String(state.APP_NAME || 'this Code App').trim();
|
|
211
180
|
const pushArgs = ['code', 'push'];
|
|
212
181
|
if (solutionUniqueName) {
|
|
213
182
|
pushArgs.push('-s', solutionUniqueName);
|
|
@@ -215,14 +184,35 @@ export default {
|
|
|
215
184
|
throw new Error('No solution unique name (SOLUTION_UNIQUE_NAME) is available. Refusing to run a bare `pac code push`, which would create the Code App outside any solution (a silent failure a later -s re-push cannot fix). Re-run the wizard solution step so the unique name is captured before deploying.');
|
|
216
185
|
}
|
|
217
186
|
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
187
|
+
// The first push with -s (the CREATE) both creates the canvasapp record and
|
|
188
|
+
// makes it a component of the chosen solution in one shot. An UPDATE push
|
|
189
|
+
// (appId already present) just republishes the existing app in place; -s is
|
|
190
|
+
// a no-op but the app stays in the solution it was created in (#81).
|
|
222
191
|
const preInfo = PAC_TARGET.loadPowerConfigInfo(powerConfigPath);
|
|
223
192
|
const isFirstPush = !preInfo.appId;
|
|
224
193
|
if (!isFirstPush) {
|
|
225
|
-
log.info(`Existing appId detected (${preInfo.appId}) — this push is an UPDATE
|
|
194
|
+
log.info(`Existing appId detected (${preInfo.appId}) — this push is an UPDATE (republish in place).`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// PRECONDITION (issue #81 follow-up): `pac code push -s` only associates the
|
|
198
|
+
// app with its solution if that UNIQUE name already EXISTS in the target
|
|
199
|
+
// environment. If it does not, pac SILENTLY publishes into the Default
|
|
200
|
+
// solution. On the FIRST push, verify the solution exists FIRST and STOP if
|
|
201
|
+
// it is absent — never let the CREATE land the app outside its solution.
|
|
202
|
+
if (isFirstPush) {
|
|
203
|
+
log.info(`Verifying solution "${solutionUniqueName}" exists in the target environment...`);
|
|
204
|
+
const solCheck = PAC_TARGET.solutionExistsInSelectedEnv({ pac, uniqueName: solutionUniqueName, cwd: projectDir });
|
|
205
|
+
if (solCheck.status === 'absent') {
|
|
206
|
+
throw new Error(`Solution "${solutionUniqueName}" does not exist in the target environment. `
|
|
207
|
+
+ `Running "pac code push -s ${solutionUniqueName}" now would SILENTLY publish the app into the Default solution `
|
|
208
|
+
+ `(the recurring "app not in my solution" failure). Create the solution in this environment (Maker Portal → Solutions → New solution, or reuse an existing one), `
|
|
209
|
+
+ `then re-run this step. Tip: the -s value must be the solution UNIQUE name, not the display name.`);
|
|
210
|
+
}
|
|
211
|
+
if (solCheck.status === 'unknown') {
|
|
212
|
+
log.warn(`Could not confirm solution "${solutionUniqueName}" exists (${solCheck.reason}). Proceeding, but if the app lands in the Default solution, verify the unique name is correct.`);
|
|
213
|
+
} else {
|
|
214
|
+
log.ok(`Solution "${solutionUniqueName}" exists in the target environment — safe to push with -s`);
|
|
215
|
+
}
|
|
226
216
|
}
|
|
227
217
|
|
|
228
218
|
const pushResult = await runFileCapture(log, pac, pushArgs, { cwd: projectDir });
|
|
@@ -246,15 +236,6 @@ export default {
|
|
|
246
236
|
log.warn('Could not detect deployed app URL in pac output. Open the app from Power Apps Maker Portal.');
|
|
247
237
|
}
|
|
248
238
|
|
|
249
|
-
// POST-PUSH MEMBERSHIP ENSURE. Read the appId the push wrote into
|
|
250
|
-
// power.config.json, confirm the app is a component of the selected
|
|
251
|
-
// solution via a Dataverse read, and add it automatically if it is not.
|
|
252
|
-
// This covers BOTH a CREATE that silently fell back to the preferred/default
|
|
253
|
-
// solution AND an UPDATE of an app that was first pushed bare (issue #81),
|
|
254
|
-
// without ever deleting or recreating the app.
|
|
255
|
-
const postInfo = PAC_TARGET.loadPowerConfigInfo(powerConfigPath);
|
|
256
|
-
await ensureAppInSolution(log, pac, projectDir, postInfo.appId, solutionUniqueName, { appDisplayName });
|
|
257
|
-
|
|
258
239
|
return { stateUpdate, completedStep: 9 };
|
|
259
240
|
},
|
|
260
241
|
};
|