sitevision-cli 1.0.0-beta.17 → 1.0.0-beta.19
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/cli.js +8 -2
- package/dist/components/AuthLoginScreen.js +3 -1
- package/dist/shell/ConfigForm.js +13 -7
- package/dist/shell/Frame.d.ts +1 -1
- package/dist/shell/Frame.js +15 -2
- package/dist/shell/Shell.d.ts +2 -1
- package/dist/shell/Shell.js +7 -5
- package/dist/shell/Tabs.js +2 -2
- package/dist/utils/i18n.js +6 -0
- package/dist/utils/project-detection.d.ts +2 -0
- package/dist/utils/project-detection.js +14 -1
- package/dist/utils/session-cookie-auth.d.ts +1 -0
- package/dist/utils/session-cookie-auth.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -30,11 +30,13 @@ const cli = meow(`
|
|
|
30
30
|
info Show project information
|
|
31
31
|
|
|
32
32
|
Options
|
|
33
|
+
--minimal Shell: compact layout for small terminals
|
|
33
34
|
--help Show this help message
|
|
34
35
|
--version Show version number
|
|
35
36
|
|
|
36
37
|
Examples
|
|
37
38
|
$ svc # Shell: run inside an app, or at the repo root
|
|
39
|
+
$ svc --minimal # Shell without the sidebar, for a small pane
|
|
38
40
|
$ svc dev
|
|
39
41
|
$ svc dev --signed
|
|
40
42
|
$ svc watch
|
|
@@ -66,6 +68,10 @@ const cli = meow(`
|
|
|
66
68
|
cookie: {
|
|
67
69
|
type: 'string',
|
|
68
70
|
},
|
|
71
|
+
minimal: {
|
|
72
|
+
type: 'boolean',
|
|
73
|
+
default: false,
|
|
74
|
+
},
|
|
69
75
|
},
|
|
70
76
|
});
|
|
71
77
|
const [commandName, ...args] = cli.input;
|
|
@@ -125,14 +131,14 @@ async function playIntro(art) {
|
|
|
125
131
|
async function runShell(apps, workspaceRoot) {
|
|
126
132
|
process.stdout.write('\x1b[?1049h\x1b[H');
|
|
127
133
|
try {
|
|
128
|
-
const art = process.stdin.isTTY && settings.introAnimation
|
|
134
|
+
const art = process.stdin.isTTY && settings.introAnimation && !cli.flags.minimal
|
|
129
135
|
? pickIntroArt(process.stdout.columns ?? 0)
|
|
130
136
|
: undefined;
|
|
131
137
|
if (art) {
|
|
132
138
|
await playIntro(art);
|
|
133
139
|
process.stdout.write('\x1b[2J\x1b[H');
|
|
134
140
|
}
|
|
135
|
-
const app = render(_jsx(Shell, { apps: apps, workspaceRoot: workspaceRoot, version: pkg.version }));
|
|
141
|
+
const app = render(_jsx(Shell, { apps: apps, workspaceRoot: workspaceRoot, version: pkg.version, minimal: cli.flags.minimal }));
|
|
136
142
|
await app.waitUntilExit();
|
|
137
143
|
}
|
|
138
144
|
finally {
|
|
@@ -15,6 +15,7 @@ export function AuthLoginScreen({ method, devProperties, onComplete, onError, on
|
|
|
15
15
|
const [phase, setPhase] = React.useState('starting');
|
|
16
16
|
const [authUrl, setAuthUrl] = React.useState('');
|
|
17
17
|
const [note, setNote] = React.useState('');
|
|
18
|
+
const [loginUrl, setLoginUrl] = React.useState('');
|
|
18
19
|
const cookieRef = React.useRef(null);
|
|
19
20
|
const cancelOAuthRef = React.useRef(null);
|
|
20
21
|
React.useEffect(() => {
|
|
@@ -45,6 +46,7 @@ export function AuthLoginScreen({ method, devProperties, onComplete, onError, on
|
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
47
48
|
cookieRef.current = session;
|
|
49
|
+
setLoginUrl(session.loginUrl);
|
|
48
50
|
setPhase('awaiting');
|
|
49
51
|
}
|
|
50
52
|
})();
|
|
@@ -84,5 +86,5 @@ export function AuthLoginScreen({ method, devProperties, onComplete, onError, on
|
|
|
84
86
|
})();
|
|
85
87
|
}
|
|
86
88
|
});
|
|
87
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: method === 'oauth2' ? t('OAuth2 login') : t('Session cookie login') }) }), method === 'oauth2' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", t('Waiting for you to finish login in the browser…')] })] }), authUrl && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: t("If the browser didn't open, visit:") }), _jsx(Text, { children: authUrl })] }))] })) : (_jsxs(Box, { flexDirection: "column", children: [phase === 'starting' && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", t('Opening browser…')] })] })), phase === 'awaiting' && (_jsx(Text, { children: t('Log in
|
|
89
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: method === 'oauth2' ? t('OAuth2 login') : t('Session cookie login') }) }), method === 'oauth2' ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", t('Waiting for you to finish login in the browser…')] })] }), authUrl && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: t("If the browser didn't open, visit:") }), _jsx(Text, { children: authUrl })] }))] })) : (_jsxs(Box, { flexDirection: "column", children: [phase === 'starting' && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", t('Opening browser…')] })] })), phase === 'awaiting' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: t('A Chrome window is open at:') }), _jsx(Text, { color: "cyan", children: loginUrl }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { children: t('1. Log in to the site there, single sign-on included.') }), _jsx(Text, { children: t('2. Wait until the site itself has finished loading.') }), _jsx(Text, { children: t('3. Come back here and press Enter.') })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t('Leave the browser window open; it closes once the session is captured.') }) })] })), phase === 'capturing' && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: _jsx(Spinner, { type: "dots" }) }), _jsxs(Text, { children: [" ", t('Capturing session…')] })] })), note && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "yellow", children: note }) }))] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t('Press Esc to cancel.') }) })] }));
|
|
88
90
|
}
|
package/dist/shell/ConfigForm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Box, Text, useInput } from 'ink';
|
|
4
|
-
import { getPackageJsonSyncChanges, readInheritedDevProperties, writeDevProperties, } from '../utils/project-detection.js';
|
|
4
|
+
import { getPackageJsonSyncChanges, normalizeDomain, readInheritedDevProperties, writeDevProperties, } from '../utils/project-detection.js';
|
|
5
5
|
import { setDeployPassword, deleteDeployPassword, getOAuth2ClientSecret, setOAuth2ClientSecret, deleteOAuth2ClientSecret, getSigningPassword, setSigningPassword, deleteSigningPassword, } from '../utils/keychain.js';
|
|
6
6
|
import { DEFAULT_SCOPES, discoverOAuth2Config } from '../utils/oauth2-auth.js';
|
|
7
7
|
import { ACCENT } from './Frame.js';
|
|
@@ -298,10 +298,16 @@ export function ConfigForm({ project, active, width, height, pickAddon, onSaved,
|
|
|
298
298
|
: [];
|
|
299
299
|
// Write one field to disk (and the keychain for secrets) right away.
|
|
300
300
|
const commit = (key, value, label = current.label) => {
|
|
301
|
-
const
|
|
301
|
+
const clean = key === 'domain' ? normalizeDomain(value) : value;
|
|
302
|
+
const next = { ...values, [key]: clean };
|
|
302
303
|
setValues(next);
|
|
303
304
|
saveConfig(project, next, new Set([key]));
|
|
304
|
-
setNote(
|
|
305
|
+
setNote(clean === value
|
|
306
|
+
? t('Saved {label}.', { label: t(label) })
|
|
307
|
+
: t('Saved {label} as {value} — a domain is a host only.', {
|
|
308
|
+
label: t(label),
|
|
309
|
+
value: clean,
|
|
310
|
+
}));
|
|
305
311
|
onSaved();
|
|
306
312
|
};
|
|
307
313
|
// Auto-fill OAuth2 endpoints from the site's OpenID configuration.
|
|
@@ -447,7 +453,7 @@ export function ConfigForm({ project, active, width, height, pickAddon, onSaved,
|
|
|
447
453
|
let lastSection;
|
|
448
454
|
for (const f of fields) {
|
|
449
455
|
if (f.section && f.section !== lastSection) {
|
|
450
|
-
rows.push(_jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, dimColor: true, children: t(f.section) }) }, `s-${f.section}`));
|
|
456
|
+
rows.push(_jsx(Box, { marginTop: 1, flexShrink: 0, children: _jsx(Text, { bold: true, dimColor: true, children: t(f.section) }) }, `s-${f.section}`));
|
|
451
457
|
lastSection = f.section;
|
|
452
458
|
}
|
|
453
459
|
const focused = active && f === current;
|
|
@@ -481,11 +487,11 @@ export function ConfigForm({ project, active, width, height, pickAddon, onSaved,
|
|
|
481
487
|
display = typing ? (withCaret(draft)) : value ? (_jsx(Text, { children: value })) : (_jsx(Text, { dimColor: true, children: f.hint ? t(f.hint) : '—' }));
|
|
482
488
|
}
|
|
483
489
|
const src = source(f);
|
|
484
|
-
rows.push(_jsxs(Box, { height: 1, children: [_jsx(Text, { color: focused ? ACCENT : undefined, bold: focused, dimColor: !focused, children: (focused ? '▸ ' : ' ') + t(f.label).padEnd(22) }), _jsx(Box, { width: valueWidth, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", children: display }) }), _jsx(Box, { width: SOURCE_WIDTH, flexShrink: 0, children: _jsx(Text, { dimColor: !src.color, color: src.color, wrap: "truncate", children: focused && f.hint && f.key === 'addonName' ? t(f.hint) : src.text }) })] }, f.key));
|
|
490
|
+
rows.push(_jsxs(Box, { height: 1, flexShrink: 0, children: [_jsx(Text, { color: focused ? ACCENT : undefined, bold: focused, dimColor: !focused, children: (focused ? '▸ ' : ' ') + t(f.label).padEnd(22) }), _jsx(Box, { width: valueWidth, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", children: display }) }), _jsx(Box, { width: SOURCE_WIDTH, flexShrink: 0, children: _jsx(Text, { dimColor: !src.color, color: src.color, wrap: "truncate", children: focused && f.hint && f.key === 'addonName' ? t(f.hint) : src.text }) })] }, f.key));
|
|
485
491
|
}
|
|
486
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", height: height, children: [_jsxs(Text, { dimColor: true, children: [(' ' + t('FIELD')).padEnd(24), t('VALUE').padEnd(valueWidth), t('SOURCE')] }), rows, project.workspace && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: t("Shared by every app below {root}. An app's own value wins.", {
|
|
492
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", height: height, children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: [(' ' + t('FIELD')).padEnd(24), t('VALUE').padEnd(valueWidth), t('SOURCE')] }) }), rows, project.workspace && (_jsx(Box, { marginTop: 1, flexShrink: 0, children: _jsx(Text, { dimColor: true, children: t("Shared by every app below {root}. An app's own value wins.", {
|
|
487
493
|
root: project.root,
|
|
488
|
-
}) }) })), !project.workspace && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { bold: true, dimColor: true, children: [t('PACKAGE.JSON SYNC'), ' ', _jsx(Text, { color: changes.length > 0 ? 'yellow' : 'green', children: changes.length === 0
|
|
494
|
+
}) }) })), !project.workspace && (_jsxs(Box, { marginTop: 1, flexDirection: "column", flexShrink: 0, children: [_jsxs(Text, { bold: true, dimColor: true, children: [t('PACKAGE.JSON SYNC'), ' ', _jsx(Text, { color: changes.length > 0 ? 'yellow' : 'green', children: changes.length === 0
|
|
489
495
|
? t('in sync')
|
|
490
496
|
: changes.length === 1
|
|
491
497
|
? t('1 diff · y to apply')
|
package/dist/shell/Frame.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface NavigatorProps {
|
|
|
47
47
|
filter?: string;
|
|
48
48
|
}
|
|
49
49
|
export declare function Navigator({ apps, groupOf, selected, focused, tasks, height, single, settingsSelected, width, filter, }: NavigatorProps): import("react").JSX.Element;
|
|
50
|
-
export declare function NavigatorStrip({ apps, selected, focused, }: Pick<NavigatorProps, 'apps' | 'selected' | 'focused'>): import("react").JSX.Element;
|
|
50
|
+
export declare function NavigatorStrip({ apps, selected, focused, width, filter, }: Pick<NavigatorProps, 'apps' | 'selected' | 'focused' | 'width' | 'filter'>): import("react").JSX.Element;
|
|
51
51
|
export declare function elapsed(task: Task): string;
|
|
52
52
|
export interface Hint {
|
|
53
53
|
key: string;
|
package/dist/shell/Frame.js
CHANGED
|
@@ -109,8 +109,21 @@ export function Navigator({ apps, groupOf, selected, focused, tasks, height, sin
|
|
|
109
109
|
? t('WORKSPACE 1 app')
|
|
110
110
|
: t('WORKSPACE {n} apps', { n: apps.length }) })), shown, _jsx(Text, { dimColor: true, children: ' ' + t('deps·config·sync·signing') }), !single && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { backgroundColor: settingsSelected && focused ? ACCENT : undefined, color: settingsSelected && focused ? 'black' : undefined, bold: settingsSelected, children: [settingsSelected ? '▎' : ' ', "\u2699 ", t('Workspace settings')] }) })), running.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { bold: true, dimColor: true, children: t('TASKS') }), running.map(task => (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { color: ACCENT, children: _jsx(Spinner, { type: "dots" }) }), ' ', task.label, " ", task.appName, " ", _jsx(Text, { dimColor: true, children: elapsed(task) })] }, task.id)))] }))] }));
|
|
111
111
|
}
|
|
112
|
-
export function NavigatorStrip({ apps, selected, focused, }) {
|
|
113
|
-
|
|
112
|
+
export function NavigatorStrip({ apps, selected, focused, width, filter = '', }) {
|
|
113
|
+
const label = (app) => ` ${typeGlyph(app.manifest)} ${appLabel(app)} `;
|
|
114
|
+
// Scroll the strip so the selection stays on screen: walk left from it
|
|
115
|
+
// until the row is full.
|
|
116
|
+
const budget = width - 2 - (filter ? filter.length + 5 : 0);
|
|
117
|
+
const from = Math.min(Math.max(0, selected), apps.length - 1);
|
|
118
|
+
let start = from;
|
|
119
|
+
let used = 0;
|
|
120
|
+
for (let i = from; i >= 0; i--) {
|
|
121
|
+
used += label(apps[i]).length;
|
|
122
|
+
if (used > budget)
|
|
123
|
+
break;
|
|
124
|
+
start = i;
|
|
125
|
+
}
|
|
126
|
+
return (_jsx(Box, { paddingX: 1, children: _jsxs(Text, { wrap: "truncate", children: [filter && (_jsxs(Text, { children: [_jsx(Text, { color: ACCENT, children: "\u276F " }), filter, _jsx(Text, { dimColor: true, children: " \u00B7" })] })), apps.slice(start).map((app, index) => (_jsx(Text, { backgroundColor: index + start === selected && focused ? ACCENT : undefined, color: index + start === selected && focused ? 'black' : undefined, bold: index + start === selected, children: label(app) }, app.root)))] }) }));
|
|
114
127
|
}
|
|
115
128
|
export function elapsed(task) {
|
|
116
129
|
const ms = (task.endedAt ?? Date.now()) - task.startedAt;
|
package/dist/shell/Shell.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ interface Props {
|
|
|
3
3
|
apps: ProjectInfo[];
|
|
4
4
|
workspaceRoot?: string;
|
|
5
5
|
version: string;
|
|
6
|
+
minimal?: boolean;
|
|
6
7
|
}
|
|
7
|
-
export declare function Shell({ apps: initialApps, workspaceRoot, version }: Props): import("react").JSX.Element;
|
|
8
|
+
export declare function Shell({ apps: initialApps, workspaceRoot, version, minimal, }: Props): import("react").JSX.Element;
|
|
8
9
|
export {};
|
package/dist/shell/Shell.js
CHANGED
|
@@ -32,7 +32,7 @@ function useSize() {
|
|
|
32
32
|
}, [stdout]);
|
|
33
33
|
return size;
|
|
34
34
|
}
|
|
35
|
-
export function Shell({ apps: initialApps, workspaceRoot, version }) {
|
|
35
|
+
export function Shell({ apps: initialApps, workspaceRoot, version, minimal = false, }) {
|
|
36
36
|
const { exit } = useApp();
|
|
37
37
|
const { columns, rows } = useSize();
|
|
38
38
|
const tasks = useTasks();
|
|
@@ -77,7 +77,7 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
|
|
|
77
77
|
// Re-read after any reload so saved values show up.
|
|
78
78
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
79
|
[workspaceRoot, apps, env]);
|
|
80
|
-
const narrow = columns < NARROW_BELOW;
|
|
80
|
+
const narrow = minimal || columns < NARROW_BELOW;
|
|
81
81
|
const sidebar = navWidth(columns);
|
|
82
82
|
// The navigator shows the fuzzy matches; `selected` stays an index into
|
|
83
83
|
// `apps` (with `apps.length` meaning the workspace settings row).
|
|
@@ -363,7 +363,9 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
|
|
|
363
363
|
run(action);
|
|
364
364
|
}, { isActive: overlay === null && !editing });
|
|
365
365
|
// Frame geometry: one row for Ink's trailing newline, top bar, bottom bar.
|
|
366
|
-
|
|
366
|
+
// The sidebar layout needs 10 rows to stack its own fixed rows without
|
|
367
|
+
// overflowing; the compact one has no sidebar and fits in 6.
|
|
368
|
+
const frameRows = Math.max(narrow ? 6 : 10, rows - 1);
|
|
367
369
|
const mainHeight = frameRows - 2;
|
|
368
370
|
const contentHeight = mainHeight - 1 - (narrow ? 1 : 0);
|
|
369
371
|
const groupOf = (app) => workspaceRoot ? appGroup(workspaceRoot, app.root) : '.';
|
|
@@ -495,9 +497,9 @@ export function Shell({ apps: initialApps, workspaceRoot, version }) {
|
|
|
495
497
|
return (_jsxs(Box, { flexDirection: "column", width: columns, height: frameRows, children: [_jsx(TopBar, { context: contextLabel, domain: project.devProperties?.domain, auth: authState(project), environment: {
|
|
496
498
|
name: env,
|
|
497
499
|
color: environmentColor(env, rawProject.devProperties),
|
|
498
|
-
}, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: matches.map(i => apps[i]), groupOf: groupOf, selected: matches.indexOf(selected), focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar, filter: filter })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: matches.map(i => apps[i]), selected: matches.indexOf(selected), focused: focus === 'nav' })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
|
|
500
|
+
}, version: version }), _jsxs(Box, { flexGrow: 1, height: mainHeight, borderStyle: "single", borderDimColor: true, borderLeft: false, borderRight: false, borderBottom: false, children: [!narrow && (_jsx(Navigator, { apps: matches.map(i => apps[i]), groupOf: groupOf, selected: matches.indexOf(selected), focused: focus === 'nav', tasks: tasks, height: mainHeight - 1, single: single, settingsSelected: settings, width: sidebar, filter: filter })), _jsxs(Box, { flexDirection: "column", width: narrow ? columns : columns - sidebar, overflow: "hidden", children: [narrow && !single && (_jsx(NavigatorStrip, { apps: matches.map(i => apps[i]), selected: matches.indexOf(selected), focused: focus === 'nav', width: columns, filter: filter })), settings ? (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: t('Workspace settings') }), _jsx(Text, { dimColor: true, children: onboard && configIncomplete(workspaceTarget?.base)
|
|
499
501
|
? t(' · new workspace: fill in once, every app inherits · Esc skips')
|
|
500
|
-
: t(' · shared .dev_properties.json at the root') })] })) : (_jsx(TabBar, { tab: tab, narrow: narrow, focused: focus === 'content' })), _jsx(Box, { height: contentHeight, overflow: "hidden", alignItems: "flex-start", children: content })] })] }), _jsx(BottomBar, { hints: hints, right: right })] }));
|
|
502
|
+
: t(' · shared .dev_properties.json at the root') })] })) : (_jsx(TabBar, { tab: tab, narrow: narrow, focused: focus === 'content' })), _jsx(Box, { flexDirection: "column", height: contentHeight, overflow: "hidden", alignItems: "flex-start", children: content })] })] }), _jsx(BottomBar, { hints: hints, right: right })] }));
|
|
501
503
|
}
|
|
502
504
|
function renderOverlay(overlay, env) {
|
|
503
505
|
const { project, closeOverlay, run, notify, loadAddons, height, rerender, openWorkspace, } = env;
|
package/dist/shell/Tabs.js
CHANGED
|
@@ -15,7 +15,7 @@ export function TabBar({ tab, narrow, focused, }) {
|
|
|
15
15
|
return (_jsx(Box, { paddingX: 1, children: TABS.map((entry, i) => (_jsxs(Text, { children: [_jsxs(Text, { bold: entry.id === tab, color: entry.id === tab ? ACCENT : undefined, dimColor: entry.id !== tab, underline: entry.id === tab && focused, children: [i + 1, " ", t(narrow ? entry.short : entry.label)] }), ' '.repeat(3)] }, entry.id))) }));
|
|
16
16
|
}
|
|
17
17
|
function Row({ label, value, dim, }) {
|
|
18
|
-
return (_jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { dimColor: true, children: label.padEnd(14) }), value, dim && _jsxs(Text, { dimColor: true, children: [" ", dim] })] }));
|
|
18
|
+
return (_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { wrap: "truncate", children: [_jsx(Text, { dimColor: true, children: label.padEnd(14) }), value, dim && _jsxs(Text, { dimColor: true, children: [" ", dim] })] }) }));
|
|
19
19
|
}
|
|
20
20
|
const LEVEL_COLOR = {
|
|
21
21
|
info: undefined,
|
|
@@ -48,7 +48,7 @@ export function Overview({ project, tasks, height, }) {
|
|
|
48
48
|
.slice(-Math.max(1, height - 18))
|
|
49
49
|
.toReversed();
|
|
50
50
|
const status = (ok, okText, badText, warn = false) => (_jsxs(Text, { children: [_jsx(Text, { color: ok ? 'green' : warn ? 'yellow' : 'red', children: ok ? '✓' : warn ? '~' : '✗' }), ' ', ok ? okText : badText] }));
|
|
51
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [_jsxs(Text, { bold: true, children: [localizedText(project.manifest.name) || project.manifest.id, ' ', _jsxs(Text, { dimColor: true, children: [project.manifest.type, project.manifest.bundled ? t(' · bundled') : ''] })] }), _jsx(Row, { label: t('id'), value: project.manifest.id }), _jsx(Row, { label: t('version'), value: project.manifest.version }), _jsx(Row, { label: t('type'), value: `${project.manifest.type} (${appTypeOf(project.manifest) ?? '?'})` }), _jsx(Row, { label: t('addon'), value: dev?.addonName ?? notSet, dim: src('addonName') }), _jsx(Row, { label: t('site'), value: dev?.siteName ?? notSet, dim: src('siteName') }), _jsx(Row, { label: t('environment'), value: dev?.environmentName ?? 'dev', dim: dev?.productionEnvironment ? t('production') : undefined }), _jsx(Row, { label: t('domain'), value: dev?.domain ?? notSet, dim: src('domain') }), _jsx(Row, { label: t('auth'), value: dev?.authMethod ?? (dev ? 'basic' : notSet), dim: src('authMethod') }), _jsx(Row, { label: t('signing user'), value: dev?.signingUsername ?? notSet, dim: src('signingUsername') }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [t('deps').padEnd(10), status(project.hasNodeModules, 'node_modules', t('missing · i to install'))] }), _jsxs(Text, { dimColor: true, children: [t('config').padEnd(10), status(Boolean(dev), t('dev properties'), t('missing · e to edit'))] }), _jsxs(Text, { dimColor: true, children: [t('sync').padEnd(10), status(sync === 0, 'package.json', sync === 1
|
|
51
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [_jsx(Box, { height: 1, flexShrink: 0, children: _jsxs(Text, { bold: true, wrap: "truncate", children: [localizedText(project.manifest.name) || project.manifest.id, ' ', _jsxs(Text, { dimColor: true, children: [project.manifest.type, project.manifest.bundled ? t(' · bundled') : ''] })] }) }), _jsx(Row, { label: t('id'), value: project.manifest.id }), _jsx(Row, { label: t('version'), value: project.manifest.version }), _jsx(Row, { label: t('type'), value: `${project.manifest.type} (${appTypeOf(project.manifest) ?? '?'})` }), _jsx(Row, { label: t('addon'), value: dev?.addonName ?? notSet, dim: src('addonName') }), _jsx(Row, { label: t('site'), value: dev?.siteName ?? notSet, dim: src('siteName') }), _jsx(Row, { label: t('environment'), value: dev?.environmentName ?? 'dev', dim: dev?.productionEnvironment ? t('production') : undefined }), _jsx(Row, { label: t('domain'), value: dev?.domain ?? notSet, dim: src('domain') }), _jsx(Row, { label: t('auth'), value: dev?.authMethod ?? (dev ? 'basic' : notSet), dim: src('authMethod') }), _jsx(Row, { label: t('signing user'), value: dev?.signingUsername ?? notSet, dim: src('signingUsername') }), _jsxs(Box, { marginTop: 1, flexDirection: "column", flexShrink: 0, children: [_jsxs(Text, { dimColor: true, children: [t('deps').padEnd(10), status(project.hasNodeModules, 'node_modules', t('missing · i to install'))] }), _jsxs(Text, { dimColor: true, children: [t('config').padEnd(10), status(Boolean(dev), t('dev properties'), t('missing · e to edit'))] }), _jsxs(Text, { dimColor: true, children: [t('sync').padEnd(10), status(sync === 0, 'package.json', sync === 1
|
|
52
52
|
? t('1 diff · y to apply')
|
|
53
53
|
: t('{n} diffs · y to apply', { n: sync }), true)] }), _jsxs(Text, { dimColor: true, children: [t('signing').padEnd(10), status(project.hasSigningProperties, dev?.signingUsername ?? '', t('missing · / set up signing'))] }), _jsxs(Text, { dimColor: true, children: [t('scripts').padEnd(10), status(scripts.status === 'ok', scripts.installed ?? '', scripts.installed
|
|
54
54
|
? `${scripts.installed} · ${scripts.status}`
|
package/dist/utils/i18n.js
CHANGED
|
@@ -230,6 +230,7 @@ const sv = {
|
|
|
230
230
|
idle: 'inaktiv',
|
|
231
231
|
'workspace config saved': 'arbetsytans konfig sparad',
|
|
232
232
|
'config saved': 'konfig sparad',
|
|
233
|
+
'Saved {label} as {value} — a domain is a host only.': 'Sparade {label} som {value} — en domän är enbart ett värdnamn.',
|
|
233
234
|
' · shared .dev_properties.json at the root': ' · delad .dev_properties.json i roten',
|
|
234
235
|
' · new workspace: fill in once, every app inherits · Esc skips': ' · ny arbetsyta: fyll i en gång, alla appar ärver · Esc hoppar över',
|
|
235
236
|
'y confirm · n cancel': 'y bekräfta · n avbryt',
|
|
@@ -267,5 +268,10 @@ const sv = {
|
|
|
267
268
|
'Opening browser…': 'Öppnar webbläsare…',
|
|
268
269
|
'Log in in the opened browser, then press Enter to capture the session.': 'Logga in i webbläsaren och tryck sedan Enter för att fånga sessionen.',
|
|
269
270
|
'Capturing session…': 'Fångar session…',
|
|
271
|
+
'A Chrome window is open at:': 'Ett Chrome-fönster är öppet på:',
|
|
272
|
+
'1. Log in to the site there, single sign-on included.': '1. Logga in på webbplatsen där, även med enkel inloggning.',
|
|
273
|
+
'2. Wait until the site itself has finished loading.': '2. Vänta tills själva webbplatsen har laddat klart.',
|
|
274
|
+
'3. Come back here and press Enter.': '3. Kom tillbaka hit och tryck Enter.',
|
|
275
|
+
'Leave the browser window open; it closes once the session is captured.': 'Låt webbläsarfönstret vara öppet; det stängs när sessionen har hämtats.',
|
|
270
276
|
'Press Esc to cancel.': 'Tryck Esc för att avbryta.',
|
|
271
277
|
};
|
|
@@ -22,6 +22,8 @@ export declare function findDevPropertiesPath(root: string): string | null;
|
|
|
22
22
|
* Get the default dev properties path (for creating new files)
|
|
23
23
|
*/
|
|
24
24
|
export declare function getDefaultDevPropertiesPath(root: string): string;
|
|
25
|
+
/** A bare host: no scheme, no path, no stray spaces. */
|
|
26
|
+
export declare function normalizeDomain(value: string): string;
|
|
25
27
|
/**
|
|
26
28
|
* The dev properties a workspace root defines (its own file merged over any
|
|
27
29
|
* ancestors'), with the deploy password resolved from the keychain like an
|
|
@@ -81,12 +81,25 @@ function ancestorDirs(root) {
|
|
|
81
81
|
}
|
|
82
82
|
return dirs;
|
|
83
83
|
}
|
|
84
|
+
/** A bare host: no scheme, no path, no stray spaces. */
|
|
85
|
+
export function normalizeDomain(value) {
|
|
86
|
+
const host = value
|
|
87
|
+
.trim()
|
|
88
|
+
.replace(/^[a-z]+:\/\//i, '')
|
|
89
|
+
.replaceAll(/\s/g, '');
|
|
90
|
+
const slash = host.indexOf('/');
|
|
91
|
+
return slash === -1 ? host : host.slice(0, slash);
|
|
92
|
+
}
|
|
84
93
|
function readDevPropertiesFile(dir) {
|
|
85
94
|
const file = findDevPropertiesPath(dir);
|
|
86
95
|
if (!file)
|
|
87
96
|
return null;
|
|
88
97
|
try {
|
|
89
|
-
|
|
98
|
+
const dev = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
99
|
+
// ponytail: top level only; a hand-edited environment override keeps its
|
|
100
|
+
// scheme until it is saved from the config form.
|
|
101
|
+
dev.domain &&= normalizeDomain(dev.domain);
|
|
102
|
+
return dev;
|
|
90
103
|
}
|
|
91
104
|
catch {
|
|
92
105
|
return null;
|