@pacaf/wizard-ux 3.4.0 → 3.4.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pacaf/wizard-ux",
3
- "version": "3.4.0",
3
+ "version": "3.4.2",
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.0"
41
+ "@pacaf/wizard": "3.4.2"
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>` associates the app on the FIRST push (the
111
- // CREATE). But several real-world paths leave it OUTSIDE the chosen solution:
112
- // a unique-name mismatch makes pac fall back to the env's preferred/default
113
- // solution, or the app was first pushed bare and a later -s re-push (an UPDATE)
114
- // is ignored. The earlier #81 design treated that as unrecoverable and told the
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')) {
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,14 @@ 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
- // PRE-PUSH NOTE. On an UPDATE push (appId already present) `-s` is ignored,
219
- // but that is no longer a dead-end: after the push we read membership from
220
- // Dataverse and add the app to the solution if needed (appId === canvasappid),
221
- // which works regardless of whether this was a CREATE or an UPDATE.
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. Solution membership will be confirmed (and repaired if needed) after the push.`);
194
+ log.info(`Existing appId detected (${preInfo.appId}) — this push is an UPDATE (republish in place).`);
226
195
  }
227
196
 
228
197
  const pushResult = await runFileCapture(log, pac, pushArgs, { cwd: projectDir });
@@ -246,15 +215,6 @@ export default {
246
215
  log.warn('Could not detect deployed app URL in pac output. Open the app from Power Apps Maker Portal.');
247
216
  }
248
217
 
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
218
  return { stateUpdate, completedStep: 9 };
259
219
  },
260
220
  };