@pacaf/wizard-ux 3.0.11 → 3.0.13
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-DrhEBZpl.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.0.
|
|
3
|
+
"version": "3.0.13",
|
|
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.1.
|
|
41
|
+
"@pacaf/wizard": "3.1.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "^19.0.0",
|
package/server/routes/state.mjs
CHANGED
|
@@ -16,6 +16,15 @@ function pickTargetEnvUrl(state) {
|
|
|
16
16
|
return { target, environmentUrl: raw.replace(/\/$/, '') };
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
// Append ?hideNavBar=true (or & form) so the Power Apps "purple bar" is hidden
|
|
20
|
+
// by default for every Code App built from this template. See issue #44 and
|
|
21
|
+
// 04-deployment.instructions.md ("Default play URL: ?hideNavBar=true").
|
|
22
|
+
function withHideNavBar(url) {
|
|
23
|
+
if (!url) return url;
|
|
24
|
+
if (/[?&]hideNavBar=/i.test(url)) return url;
|
|
25
|
+
return url + (url.includes('?') ? '&' : '?') + 'hideNavBar=true';
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
function readPowerAppInfo(rootDir, state) {
|
|
20
29
|
const projectDir = resolve(rootDir, String(state.PROJECT_DIR || '.'));
|
|
21
30
|
const powerConfigPath = join(projectDir, 'power.config.json');
|
|
@@ -43,7 +52,7 @@ function readPowerAppInfo(rootDir, state) {
|
|
|
43
52
|
appId,
|
|
44
53
|
targetEnv: target,
|
|
45
54
|
environmentUrl,
|
|
46
|
-
launchUrl: deployedUrl,
|
|
55
|
+
launchUrl: withHideNavBar(deployedUrl),
|
|
47
56
|
};
|
|
48
57
|
}
|
|
49
58
|
|
|
@@ -40,7 +40,9 @@ function runCommand(log, command, opts = {}) {
|
|
|
40
40
|
function runFile(log, file, args, opts = {}) {
|
|
41
41
|
return new Promise((resolvePromise) => {
|
|
42
42
|
log.info(`$ ${SHELL.formatCommandForLog(file, args)}`);
|
|
43
|
-
const
|
|
43
|
+
const spawnOpts = { cwd: opts.cwd || process.cwd(), stdio: ['ignore', 'pipe', 'pipe'] };
|
|
44
|
+
if (opts.env) spawnOpts.env = opts.env;
|
|
45
|
+
const child = SHELL.spawnSafe(file, args, spawnOpts);
|
|
44
46
|
child.stdout.setEncoding('utf-8');
|
|
45
47
|
child.stderr.setEncoding('utf-8');
|
|
46
48
|
child.stdout.on('data', (chunk) => log.info(String(chunk).trimEnd()));
|
|
@@ -53,6 +55,47 @@ function runFile(log, file, args, opts = {}) {
|
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
// Build a noisy-but-reassuring env for `npm install` / `pnpm install` so the
|
|
59
|
+
// SSE-piped output stops looking frozen during long cold installs:
|
|
60
|
+
// - `npm_config_loglevel=http` is added at the CLI level (so it shows the
|
|
61
|
+
// `npm http fetch ...` per-package line).
|
|
62
|
+
// - `npm_config_progress=true` keeps progress hints on (npm still suppresses
|
|
63
|
+
// its TTY bar but at least won't strip extra hints).
|
|
64
|
+
// - `FORCE_COLOR=0` keeps ANSI escapes out of the SSE stream.
|
|
65
|
+
// - `CI` is unset to avoid npm dropping output thinking it is in CI.
|
|
66
|
+
function installEnv() {
|
|
67
|
+
const env = { ...process.env, npm_config_progress: 'true', FORCE_COLOR: '0' };
|
|
68
|
+
delete env.CI;
|
|
69
|
+
return env;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Detect whether `pnpm` is available on PATH. pnpm prints staged progress
|
|
73
|
+
// (`Progress: resolved X, reused Y, downloaded Z`) even in non-TTY mode and
|
|
74
|
+
// is materially faster on a cold cache, so prefer it when present.
|
|
75
|
+
function detectPnpm() {
|
|
76
|
+
try {
|
|
77
|
+
execFileSync(process.platform === 'win32' ? 'where' : 'which', ['pnpm'], { stdio: 'ignore' });
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function runInstall(log, { stage, label, projectDir, pnpm, mode, packages = [] }) {
|
|
85
|
+
log.info('');
|
|
86
|
+
log.info(`[${stage}] ${label} (typically 30s–3min on a cold cache)…`);
|
|
87
|
+
const bin = pnpm
|
|
88
|
+
? toolCommand('pnpm')
|
|
89
|
+
: toolCommand('npm');
|
|
90
|
+
const baseArgs = pnpm
|
|
91
|
+
? (mode === 'base' ? ['install'] : mode === 'dev' ? ['add', '-D', ...packages] : ['add', ...packages])
|
|
92
|
+
: (mode === 'base' ? ['install'] : mode === 'dev' ? ['install', '-D', ...packages] : ['install', ...packages]);
|
|
93
|
+
const noisyArgs = pnpm
|
|
94
|
+
? ['--reporter=append-only', ...baseArgs]
|
|
95
|
+
: ['--loglevel=http', '--no-audit', '--no-fund', ...baseArgs];
|
|
96
|
+
return runFile(log, bin, noisyArgs, { cwd: projectDir, env: installEnv() });
|
|
97
|
+
}
|
|
98
|
+
|
|
56
99
|
function toolCommand(name) {
|
|
57
100
|
return process.platform === 'win32' ? `${name}.cmd` : name;
|
|
58
101
|
}
|
|
@@ -233,16 +276,32 @@ export default {
|
|
|
233
276
|
}
|
|
234
277
|
|
|
235
278
|
log.info('Installing dependencies...');
|
|
236
|
-
|
|
237
|
-
|
|
279
|
+
const pnpm = detectPnpm();
|
|
280
|
+
if (pnpm) {
|
|
281
|
+
log.info('Detected pnpm — using it for faster installs and shared dependency cache.');
|
|
282
|
+
} else {
|
|
283
|
+
log.info('pnpm not found — using npm. Tip: `corepack enable && corepack prepare pnpm@latest --activate` makes Step 7 noticeably faster.');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (await runInstall(log, { stage: '1/3', label: 'Installing base dependencies', projectDir, pnpm, mode: 'base' })) {
|
|
287
|
+
log.ok('[1/3] Base dependencies installed');
|
|
288
|
+
} else {
|
|
289
|
+
log.warn('[1/3] Base dependency install reported errors; continuing to merge required packages.');
|
|
290
|
+
}
|
|
238
291
|
|
|
239
292
|
const prodPkgs = SCAFFOLD.packageSpecs(SCAFFOLD.REQUIRED_RUNTIME_PACKAGES);
|
|
240
|
-
if (await
|
|
241
|
-
|
|
293
|
+
if (await runInstall(log, { stage: '2/3', label: 'Installing runtime packages (React, Fluent UI, TanStack Query, SDK)', projectDir, pnpm, mode: 'prod', packages: prodPkgs })) {
|
|
294
|
+
log.ok('[2/3] Runtime packages installed');
|
|
295
|
+
} else {
|
|
296
|
+
log.warn('[2/3] Some runtime packages failed to install.');
|
|
297
|
+
}
|
|
242
298
|
|
|
243
299
|
const devPkgs = SCAFFOLD.packageSpecs(SCAFFOLD.REQUIRED_DEV_PACKAGES);
|
|
244
|
-
if (await
|
|
245
|
-
|
|
300
|
+
if (await runInstall(log, { stage: '3/3', label: 'Installing dev dependencies (Vitest, ESLint, Playwright, @pacaf/scripts)', projectDir, pnpm, mode: 'dev', packages: devPkgs })) {
|
|
301
|
+
log.ok('[3/3] Dev packages installed');
|
|
302
|
+
} else {
|
|
303
|
+
log.warn('[3/3] Some dev packages failed to install.');
|
|
304
|
+
}
|
|
246
305
|
|
|
247
306
|
SCAFFOLD.writeConfig(projectDir, foundationLogger);
|
|
248
307
|
SCAFFOLD.mergePackageJsonScripts(projectDir, foundationLogger);
|
|
@@ -82,6 +82,16 @@ function runFileCapture(log, file, args, opts = {}) {
|
|
|
82
82
|
|
|
83
83
|
const PAC_HTTP_ERROR_RE = /HTTP error status:\s*[45]\d\d/i;
|
|
84
84
|
|
|
85
|
+
// Append ?hideNavBar=true (or &hideNavBar=true if the URL already has a query
|
|
86
|
+
// string) so the Power Apps "purple bar" — the top chrome rendered by the
|
|
87
|
+
// Power Apps host around any Code App — is hidden by default. See
|
|
88
|
+
// .github/instructions/04-deployment.instructions.md and issue #44.
|
|
89
|
+
function withHideNavBar(url) {
|
|
90
|
+
if (!url) return url;
|
|
91
|
+
if (/[?&]hideNavBar=/i.test(url)) return url;
|
|
92
|
+
return url + (url.includes('?') ? '&' : '?') + 'hideNavBar=true';
|
|
93
|
+
}
|
|
94
|
+
|
|
85
95
|
function resolveCredentialValues(state) {
|
|
86
96
|
return PAC_TARGET.resolveCredentialValues({
|
|
87
97
|
rootDir: PROJECT_DIR,
|
|
@@ -198,10 +208,12 @@ export default {
|
|
|
198
208
|
// "The app was successfully published. URL: https://apps.powerapps.com/play/e/<envId>/a/<appId>"
|
|
199
209
|
// Capture the first matching apps.powerapps.com/play URL and persist it
|
|
200
210
|
// to wizard state so the Summary can show the real launch URL.
|
|
211
|
+
// Always append ?hideNavBar=true so the deployed app hides the Power
|
|
212
|
+
// Apps "purple bar" by default (see issue #44 and 04-deployment.instructions.md).
|
|
201
213
|
const deployedUrlMatch = pushOutput.match(/https:\/\/apps\.powerapps\.com\/play\/[^\s'"<>)]+/i);
|
|
202
214
|
const stateUpdate = { PROJECT_DIR: projectDir };
|
|
203
215
|
if (deployedUrlMatch) {
|
|
204
|
-
const deployedUrl = deployedUrlMatch[0].replace(/[.,;]+$/, '');
|
|
216
|
+
const deployedUrl = withHideNavBar(deployedUrlMatch[0].replace(/[.,;]+$/, ''));
|
|
205
217
|
stateUpdate.DEPLOYED_APP_URL = deployedUrl;
|
|
206
218
|
log.ok(`App URL: ${deployedUrl}`);
|
|
207
219
|
} else {
|