sitevision-cli 1.0.0-beta.12 → 1.0.0-beta.14
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 +70 -41
- package/dist/commands/build.js +1 -1
- package/dist/commands/dev.d.ts +8 -10
- package/dist/commands/dev.js +75 -390
- package/dist/commands/watch.js +5 -23
- package/dist/components/AuthLoginScreen.js +4 -3
- package/dist/components/DevPropertiesForm.js +6 -3
- package/dist/components/PasswordInput.js +2 -1
- package/dist/shell/AddonPicker.d.ts +14 -0
- package/dist/shell/AddonPicker.js +54 -0
- package/dist/shell/CommandPalette.d.ts +8 -0
- package/dist/shell/CommandPalette.js +63 -0
- package/dist/shell/ConfigForm.d.ts +35 -0
- package/dist/shell/ConfigForm.js +472 -0
- package/dist/shell/Frame.d.ts +52 -0
- package/dist/shell/Frame.js +98 -0
- package/dist/shell/Settings.d.ts +6 -0
- package/dist/shell/Settings.js +96 -0
- package/dist/shell/Shell.d.ts +8 -0
- package/dist/shell/Shell.js +520 -0
- package/dist/shell/Tabs.d.ts +36 -0
- package/dist/shell/Tabs.js +85 -0
- package/dist/shell/actions.d.ts +45 -0
- package/dist/shell/actions.js +0 -0
- package/dist/types/index.d.ts +12 -2
- package/dist/utils/config.d.ts +10 -0
- package/dist/utils/config.js +14 -0
- package/dist/utils/environments.d.ts +20 -0
- package/dist/utils/environments.js +74 -0
- package/dist/utils/i18n.d.ts +12 -0
- package/dist/utils/i18n.js +263 -0
- package/dist/utils/oauth2-auth.d.ts +26 -1
- package/dist/utils/oauth2-auth.js +75 -32
- package/dist/utils/project-detection.d.ts +23 -1
- package/dist/utils/project-detection.js +124 -51
- package/dist/utils/sitevision-api.d.ts +35 -0
- package/dist/utils/sitevision-api.js +74 -1
- package/dist/utils/tasks.d.ts +48 -0
- package/dist/utils/tasks.js +371 -0
- package/dist/utils/workspace.d.ts +8 -0
- package/dist/utils/workspace.js +48 -0
- package/package.json +1 -1
- package/readme.md +76 -24
package/dist/cli.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { render } from 'ink';
|
|
4
4
|
import { Text, Box } from 'ink';
|
|
5
5
|
import meow from 'meow';
|
|
6
6
|
import { readFileSync } from 'node:fs';
|
|
7
|
-
import
|
|
7
|
+
import { Shell } from './shell/Shell.js';
|
|
8
8
|
import { getCommand } from './commands/index.js';
|
|
9
|
-
import { requireProject, migrateLegacyPassword, } from './utils/project-detection.js';
|
|
9
|
+
import { requireProject, detectProject, migrateLegacyPassword, } from './utils/project-detection.js';
|
|
10
|
+
import { discoverApps } from './utils/workspace.js';
|
|
10
11
|
import { promptYesNo } from './utils/password-prompt.js';
|
|
11
12
|
import { checkForUpdate } from './utils/version-check.js';
|
|
12
|
-
import { isFirstRun, markFirstRunComplete, getLastSeenVersion, setLastSeenVersion, } from './utils/config.js';
|
|
13
|
+
import { isFirstRun, markFirstRunComplete, getLastSeenVersion, setLastSeenVersion, getSettings, } from './utils/config.js';
|
|
14
|
+
import { setLanguage } from './utils/i18n.js';
|
|
13
15
|
import { WelcomeScreen } from './components/WelcomeScreen.js';
|
|
14
16
|
import { AnimatedLogo } from './components/AnimatedLogo.js';
|
|
15
17
|
import { printBranding, BIG_LOGO, BIG_LOGO_WIDTH, SMALL_LOGO, SMALL_LOGO_WIDTH, } from './utils/branding.js';
|
|
16
18
|
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
17
19
|
const cli = meow(`
|
|
18
20
|
Usage
|
|
19
|
-
$ svc
|
|
21
|
+
$ svc Open the interactive shell (app or workspace)
|
|
20
22
|
$ svc <command> [options]
|
|
21
23
|
|
|
22
24
|
Commands
|
|
@@ -32,7 +34,7 @@ const cli = meow(`
|
|
|
32
34
|
--version Show version number
|
|
33
35
|
|
|
34
36
|
Examples
|
|
35
|
-
$ svc #
|
|
37
|
+
$ svc # Shell: run inside an app, or at the repo root
|
|
36
38
|
$ svc dev
|
|
37
39
|
$ svc dev --signed
|
|
38
40
|
$ svc watch
|
|
@@ -67,6 +69,8 @@ const cli = meow(`
|
|
|
67
69
|
},
|
|
68
70
|
});
|
|
69
71
|
const [commandName, ...args] = cli.input;
|
|
72
|
+
const settings = getSettings();
|
|
73
|
+
setLanguage(settings.language);
|
|
70
74
|
const CYAN = '\x1b[36m';
|
|
71
75
|
const BOLD = '\x1b[1m';
|
|
72
76
|
const DIM = '\x1b[2m';
|
|
@@ -95,8 +99,12 @@ function printMasthead(version) {
|
|
|
95
99
|
`${spaces(gap)}${DIM}${right}${RESET}${spaces(padding)}${CYAN}│${RESET}`);
|
|
96
100
|
console.log(`${CYAN}╰${border}╯${RESET}`);
|
|
97
101
|
}
|
|
102
|
+
function fail(message, hint) {
|
|
103
|
+
render(_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Text, { color: "red", children: ["Error: ", message] }), _jsx(Text, { dimColor: true, children: hint })] }));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
98
106
|
// Pick the widest wordmark that fits the terminal, or undefined if even the
|
|
99
|
-
// compact one would wrap
|
|
107
|
+
// compact one would wrap.
|
|
100
108
|
function pickIntroArt(columns) {
|
|
101
109
|
if (columns >= BIG_LOGO_WIDTH)
|
|
102
110
|
return BIG_LOGO;
|
|
@@ -111,6 +119,26 @@ async function playIntro(art) {
|
|
|
111
119
|
app.waitUntilExit().then(() => resolve(), () => resolve());
|
|
112
120
|
});
|
|
113
121
|
}
|
|
122
|
+
// Run the full-screen shell on the alternate screen buffer so the scrollback
|
|
123
|
+
// is untouched, and restore it on exit. The animated wordmark plays first,
|
|
124
|
+
// inside the same buffer, when the terminal is wide enough for it.
|
|
125
|
+
async function runShell(apps, workspaceRoot) {
|
|
126
|
+
process.stdout.write('\x1b[?1049h\x1b[H');
|
|
127
|
+
try {
|
|
128
|
+
const art = process.stdin.isTTY && settings.introAnimation
|
|
129
|
+
? pickIntroArt(process.stdout.columns ?? 0)
|
|
130
|
+
: undefined;
|
|
131
|
+
if (art) {
|
|
132
|
+
await playIntro(art);
|
|
133
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
134
|
+
}
|
|
135
|
+
const app = render(_jsx(Shell, { apps: apps, workspaceRoot: workspaceRoot, version: pkg.version }));
|
|
136
|
+
await app.waitUntilExit();
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
process.stdout.write('\x1b[?1049l');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
114
142
|
async function main() {
|
|
115
143
|
// On the very first run we show a dedicated welcome screen instead of the
|
|
116
144
|
// masthead, so the branding is the moment. Only when stdin is a TTY — the
|
|
@@ -122,19 +150,12 @@ async function main() {
|
|
|
122
150
|
// silently rather than claiming an update happened.
|
|
123
151
|
const lastSeen = getLastSeenVersion();
|
|
124
152
|
const isUpdate = !firstRun && lastSeen !== undefined && lastSeen !== pkg.version;
|
|
125
|
-
// On the plain interactive `svc` (no command), play the animated wordmark
|
|
126
|
-
// instead of the static masthead — sized to the terminal. Only on a TTY so it
|
|
127
|
-
// doesn't run in CI / piped input.
|
|
128
|
-
const introEligible = !firstRun && !isUpdate && !commandName && Boolean(process.stdin.isTTY);
|
|
129
|
-
const introArt = introEligible
|
|
130
|
-
? pickIntroArt(process.stdout.columns ?? 0)
|
|
131
|
-
: undefined;
|
|
132
153
|
if (!firstRun) {
|
|
133
154
|
if (isUpdate) {
|
|
134
155
|
printBranding();
|
|
135
156
|
console.log(`\x1b[32m\n ✨ Updated to v${pkg.version}\x1b[0m \x1b[2m(from v${lastSeen})\x1b[0m\n`);
|
|
136
157
|
}
|
|
137
|
-
else if (
|
|
158
|
+
else if (commandName) {
|
|
138
159
|
printMasthead(pkg.version);
|
|
139
160
|
}
|
|
140
161
|
// Record the current version so the banner shows once per upgrade.
|
|
@@ -145,14 +166,44 @@ async function main() {
|
|
|
145
166
|
console.log(`\x1b[33m ↑ update available: ${pkg.version} → ${latestVersion} (run: npm i -g ${pkg.name})\x1b[0m`);
|
|
146
167
|
}
|
|
147
168
|
}
|
|
169
|
+
// No command: the shell. Inside an app it is single-app mode; anywhere
|
|
170
|
+
// above one or more apps it is workspace mode.
|
|
171
|
+
if (!commandName) {
|
|
172
|
+
let project = null;
|
|
173
|
+
try {
|
|
174
|
+
project = detectProject();
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
fail(error.message, 'Fix the manifest and try again');
|
|
178
|
+
}
|
|
179
|
+
if (!project) {
|
|
180
|
+
const apps = discoverApps(process.cwd());
|
|
181
|
+
if (apps.length === 0) {
|
|
182
|
+
fail('No Sitevision apps found here.', 'Run svc inside an app directory (manifest.json) or at the root of a repo that contains apps.');
|
|
183
|
+
}
|
|
184
|
+
await runShell(apps, process.cwd());
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (firstRun) {
|
|
188
|
+
await new Promise(resolve => {
|
|
189
|
+
const app = render(_jsx(WelcomeScreen, { project: project, onComplete: () => {
|
|
190
|
+
markFirstRunComplete();
|
|
191
|
+
setLastSeenVersion(pkg.version);
|
|
192
|
+
app.unmount();
|
|
193
|
+
} }));
|
|
194
|
+
app.waitUntilExit().then(() => resolve(), () => resolve());
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
await runShell([project]);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
148
200
|
// Check if we're in a Sitevision project
|
|
149
201
|
const project = (() => {
|
|
150
202
|
try {
|
|
151
203
|
return requireProject();
|
|
152
204
|
}
|
|
153
205
|
catch (error) {
|
|
154
|
-
|
|
155
|
-
process.exit(1);
|
|
206
|
+
return fail(error.message, "Make sure you're in a Sitevision project directory");
|
|
156
207
|
}
|
|
157
208
|
})();
|
|
158
209
|
// --token / --cookie override the resolved bearer token / session cookie for
|
|
@@ -171,27 +222,6 @@ async function main() {
|
|
|
171
222
|
console.log('\x1b[33m--token/--cookie needs a .dev_properties.json (domain, site, addon) to deploy against.\x1b[0m');
|
|
172
223
|
}
|
|
173
224
|
}
|
|
174
|
-
// First run: show the welcome (branding + optional signing-password save),
|
|
175
|
-
// then continue to the normal flow once the user dismisses it.
|
|
176
|
-
if (firstRun) {
|
|
177
|
-
await new Promise(resolve => {
|
|
178
|
-
const app = render(_jsx(WelcomeScreen, { project: project, onComplete: () => {
|
|
179
|
-
markFirstRunComplete();
|
|
180
|
-
setLastSeenVersion(pkg.version);
|
|
181
|
-
app.unmount();
|
|
182
|
-
} }));
|
|
183
|
-
app.waitUntilExit().then(() => resolve(), () => resolve());
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
// If no command, show interactive menu (with the animated intro first when
|
|
187
|
-
// the terminal can fit it).
|
|
188
|
-
if (!commandName) {
|
|
189
|
-
if (introArt) {
|
|
190
|
-
await playIntro(introArt);
|
|
191
|
-
}
|
|
192
|
-
render(_jsx(App, { project: project }));
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
225
|
// Get the command
|
|
196
226
|
const command = getCommand(commandName);
|
|
197
227
|
if (!command) {
|
|
@@ -199,9 +229,8 @@ async function main() {
|
|
|
199
229
|
process.exit(1);
|
|
200
230
|
}
|
|
201
231
|
// Offer to migrate a legacy plaintext password into the OS keychain.
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
// would fail — the plaintext password is still used for this run.
|
|
232
|
+
// Skip on non-TTY stdin (e.g. CI) where prompting would fail — the
|
|
233
|
+
// plaintext password is still used for this run.
|
|
205
234
|
if (project.hasLegacyPassword && process.stdin.isTTY) {
|
|
206
235
|
console.log('\n\x1b[33m⚠ Plaintext password found in .dev_properties.json\x1b[0m');
|
|
207
236
|
const move = await promptYesNo('Move it to the OS keychain and remove it from the file? (y/N): ');
|
package/dist/commands/build.js
CHANGED
|
@@ -87,7 +87,7 @@ export function BuildScreen({ projectRoot, manifest, createZip = true, onBack, }
|
|
|
87
87
|
const runner = new WebpackRunner(projectRoot, {
|
|
88
88
|
mode: 'production',
|
|
89
89
|
cssPrefix: manifest.id,
|
|
90
|
-
restApp: appType
|
|
90
|
+
restApp: appType !== 'web' && appType !== 'widget',
|
|
91
91
|
});
|
|
92
92
|
const result = await runner.run();
|
|
93
93
|
await runner.close();
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type Command } from './types.js';
|
|
3
|
-
import
|
|
3
|
+
import { type DevOptions } from '../utils/tasks.js';
|
|
4
|
+
import type { ProjectInfo, SigningCredentials } from '../types/index.js';
|
|
4
5
|
interface DevScreenProps {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
devProperties?: DevProperties;
|
|
8
|
-
signed: boolean;
|
|
9
|
-
deploy?: boolean;
|
|
10
|
-
signingCredentials?: SigningCredentials;
|
|
11
|
-
onBack?: () => void;
|
|
12
|
-
onRetryCredentials?: () => void;
|
|
6
|
+
project: ProjectInfo;
|
|
7
|
+
options: DevOptions;
|
|
13
8
|
}
|
|
14
|
-
|
|
9
|
+
/** Standalone `svc dev` / `svc watch`: one task, its log, Ctrl+C or q to stop. */
|
|
10
|
+
export declare function DevScreen({ project, options }: DevScreenProps): React.JSX.Element;
|
|
11
|
+
/** Resolve signing credentials for signed dev/watch, prompting if needed. */
|
|
12
|
+
export declare function resolveSigningForCli(project: ProjectInfo): Promise<SigningCredentials | undefined>;
|
|
15
13
|
export declare const devCommand: Command;
|
|
16
14
|
export {};
|