@galda/cli 0.10.80 → 0.10.82
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/app/index.html +4 -9
- package/engine/lib.mjs +7 -1
- package/engine/server.mjs +8 -4
- package/package.json +1 -1
package/app/index.html
CHANGED
|
@@ -10628,7 +10628,7 @@ function renderCtxBar(){
|
|
|
10628
10628
|
+ `<span class="pt">\u200e${esc(folderShort(r.dir))}</span></button>`)
|
|
10629
10629
|
.join('');
|
|
10630
10630
|
const openRow = `<button type="button" class="appopt ctxopen" id="ctxopenfolder" title="Open the OS folder chooser"><svg viewBox="0 0 24 24"><path d="M3 7a2 2 0 012-2h4l2 2h8a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><path d="M12 11v6M9 14h6"/></svg><span class="nm">Open folder…</span></button>`;
|
|
10631
|
-
menu.innerHTML = `${opts}${openRow}<div class="
|
|
10631
|
+
menu.innerHTML = `${opts}${openRow}<div class="ctxmsg" id="ctxdirmsg"></div>`;
|
|
10632
10632
|
}
|
|
10633
10633
|
// Workspace mode is fixed to the isolated worktree (clean separate checkout). The
|
|
10634
10634
|
// direct-workspace escape hatch was removed after two accidents where a stray click
|
|
@@ -10656,7 +10656,7 @@ async function setProjectFolder(dir){
|
|
|
10656
10656
|
const want = String(dir ?? '').trim();
|
|
10657
10657
|
const msg = $('ctxdirmsg');
|
|
10658
10658
|
const say = (t, bad) => { if (msg) { msg.textContent = t; msg.classList.toggle('bad', Boolean(bad)); } };
|
|
10659
|
-
if (!want) { say('
|
|
10659
|
+
if (!want) { say('Choose a folder.', true); return; }
|
|
10660
10660
|
say('');
|
|
10661
10661
|
try {
|
|
10662
10662
|
const r = await fetch(withKey(`/api/projects/${encodeURIComponent(state.active)}`), {
|
|
@@ -10678,14 +10678,14 @@ function isLocalSession(){ return ['localhost', '127.0.0.1'].includes(location.h
|
|
|
10678
10678
|
async function openFolderNative(){
|
|
10679
10679
|
const msg = $('ctxdirmsg');
|
|
10680
10680
|
const say = (t, bad) => { if (msg) { msg.textContent = t; msg.classList.toggle('bad', Boolean(bad)); } };
|
|
10681
|
-
if (!isLocalSession()) {
|
|
10681
|
+
if (!isLocalSession()) { say('Open Manager locally to choose a folder on this computer.', true); return; }
|
|
10682
10682
|
say('Opening the folder chooser…');
|
|
10683
10683
|
try {
|
|
10684
10684
|
const r = await fetch(withKey('/api/choose-folder'), { method: 'POST' });
|
|
10685
10685
|
const body = await r.json().catch(() => ({}));
|
|
10686
10686
|
if (body.path) { setProjectFolder(body.path); return; } // reuse: PUT the project's dir, close, render
|
|
10687
10687
|
if (body.cancelled) { say(''); return; }
|
|
10688
|
-
if (body.unsupported) { say('This engine can’t open a folder dialog
|
|
10688
|
+
if (body.unsupported) { say('This engine can’t open a folder dialog on this system.', true); return; }
|
|
10689
10689
|
say(body.error || 'Could not open the folder chooser.', true);
|
|
10690
10690
|
} catch { say('Could not reach the engine.', true); }
|
|
10691
10691
|
}
|
|
@@ -10701,11 +10701,6 @@ $('ctxdirmenu').addEventListener('click', (e) => {
|
|
|
10701
10701
|
if (e.target.closest('#ctxopenfolder')) { openFolderNative(); return; }
|
|
10702
10702
|
const opt = e.target.closest('[data-ctxdir]');
|
|
10703
10703
|
if (opt) { setProjectFolder(opt.dataset.ctxdir); return; }
|
|
10704
|
-
if (e.target.closest('#ctxdiruse')) setProjectFolder($('ctxdirin')?.value ?? '');
|
|
10705
|
-
});
|
|
10706
|
-
$('ctxdirmenu').addEventListener('keydown', (e) => {
|
|
10707
|
-
e.stopPropagation();
|
|
10708
|
-
if (e.key === 'Enter' && !e.isComposing && e.target.id === 'ctxdirin') { e.preventDefault(); setProjectFolder(e.target.value); }
|
|
10709
10704
|
});
|
|
10710
10705
|
$('appbtn').onclick = (e) => { e.stopPropagation(); $('appmenu').classList.toggle('show'); };
|
|
10711
10706
|
$('appmenu').addEventListener('click', (e) => {
|
package/engine/lib.mjs
CHANGED
|
@@ -97,8 +97,14 @@ export function rebasePreviewUrl(declaredUrl, serverUrl) {
|
|
|
97
97
|
const declared = new URL(declaredUrl);
|
|
98
98
|
const server = new URL(serverUrl);
|
|
99
99
|
const params = new URLSearchParams(declared.search);
|
|
100
|
+
// The isolated preview is a different Manager instance with its own
|
|
101
|
+
// secret.key. A worker declaration can carry the parent instance's stale
|
|
102
|
+
// `key`, but that credential can never authenticate the ephemeral server.
|
|
103
|
+
// Preserve all artifact parameters while making the target server the
|
|
104
|
+
// authority for authentication.
|
|
105
|
+
if (server.searchParams.has('key')) params.delete('key');
|
|
100
106
|
for (const [key, value] of server.searchParams) {
|
|
101
|
-
if (!params.has(key)) params.set(key, value);
|
|
107
|
+
if (!params.has(key) || key === 'key') params.set(key, value);
|
|
102
108
|
}
|
|
103
109
|
server.pathname = declared.pathname || '/';
|
|
104
110
|
server.search = params.toString();
|
package/engine/server.mjs
CHANGED
|
@@ -4101,13 +4101,17 @@ const server = createServer(async (req, res) => {
|
|
|
4101
4101
|
// (otherwise the dialog would open on the server, not the person's screen). It
|
|
4102
4102
|
// returns only the chosen path — nothing is scanned, listed, or invented.
|
|
4103
4103
|
// { path, label } | { cancelled: true } | { unsupported: true } | { error }
|
|
4104
|
-
// MANAGER_NO_NATIVE_DIALOG
|
|
4105
|
-
//
|
|
4104
|
+
// MANAGER_NO_NATIVE_DIALOG short-circuits so tests/CI/headless never block
|
|
4105
|
+
// on a GUI. macOS, Windows and common Linux desktops use their native picker.
|
|
4106
4106
|
if (url.pathname === '/api/choose-folder' && req.method === 'POST') {
|
|
4107
|
-
if (process.
|
|
4107
|
+
if (process.env.MANAGER_NO_NATIVE_DIALOG) {
|
|
4108
4108
|
return json(res, 200, { unsupported: true });
|
|
4109
4109
|
}
|
|
4110
|
-
|
|
4110
|
+
const windowsScript = 'Add-Type -AssemblyName System.Windows.Forms; $d = New-Object System.Windows.Forms.FolderBrowserDialog; if ($d.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Write($d.SelectedPath) }';
|
|
4111
|
+
const command = process.platform === 'darwin' ? 'osascript' : process.platform === 'win32' ? 'powershell.exe' : 'zenity';
|
|
4112
|
+
const args = process.platform === 'darwin' ? ['-e', chooseFolderScript()] : process.platform === 'win32'
|
|
4113
|
+
? ['-NoProfile', '-NonInteractive', '-Command', windowsScript] : ['--file-selection', '--directory', '--title=Choose a project folder'];
|
|
4114
|
+
execFile(command, args, { timeout: 120000 }, (err, stdout, stderr) => {
|
|
4111
4115
|
const verdict = parseChosenFolder({ code: err ? (err.code ?? 1) : 0, stdout, stderr });
|
|
4112
4116
|
if (verdict.path) verdict.label = folderLabel(verdict.path, HOME);
|
|
4113
4117
|
json(res, 200, verdict);
|
package/package.json
CHANGED