sitevision-cli 1.0.0-beta.9 → 1.0.0
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/CHANGELOG.md +138 -0
- package/LICENSE +21 -0
- package/dist/cli.js +194 -70
- package/dist/commands/TaskScreen.js +32 -0
- package/dist/commands/build.js +6 -185
- package/dist/commands/deploy.js +95 -212
- package/dist/commands/dev.js +87 -416
- package/dist/commands/info.js +1 -1
- package/dist/commands/setup-signing.js +50 -33
- package/dist/commands/sign.js +9 -86
- package/dist/commands/use-finish.js +17 -0
- package/dist/commands/watch.js +5 -31
- package/dist/components/AnimatedLogo.js +8 -2
- package/dist/components/AuthLoginScreen.js +33 -15
- package/dist/components/PasswordInput.js +2 -1
- package/dist/scaffold/inquirer-stub.js +119 -0
- package/dist/scaffold/register.js +15 -0
- package/dist/shell/AddonPicker.js +54 -0
- package/dist/shell/Changelog.js +44 -0
- package/dist/shell/CommandPalette.js +63 -0
- package/dist/shell/ConfigForm.js +703 -0
- package/dist/shell/Frame.js +138 -0
- package/dist/shell/Help.js +96 -0
- package/dist/shell/Popover.js +15 -0
- package/dist/shell/Settings.js +149 -0
- package/dist/shell/Shell.js +953 -0
- package/dist/shell/Tabs.js +96 -0
- package/dist/shell/actions.js +493 -0
- package/dist/utils/config.js +62 -2
- package/dist/utils/create-app.js +231 -0
- package/dist/utils/debug.js +32 -0
- package/dist/utils/environments.js +74 -0
- package/dist/utils/i18n.js +369 -0
- package/dist/utils/jsonc.js +2 -1
- package/dist/utils/keychain.js +54 -6
- package/dist/utils/oauth2-auth.js +146 -43
- package/dist/utils/password-prompt.js +37 -3
- package/dist/utils/process-runner.js +77 -38
- package/dist/utils/project-detection.js +457 -112
- package/dist/utils/session-cookie-auth.js +10 -6
- package/dist/utils/sitevision-api.js +134 -25
- package/dist/utils/sitevision-scripts-runner.js +50 -22
- package/dist/utils/tasks.js +510 -0
- package/dist/utils/version-check.js +3 -3
- package/dist/utils/webpack-runner.js +9 -5
- package/dist/utils/workspace.js +105 -0
- package/dist/utils/zip.js +18 -19
- package/package.json +27 -4
- package/readme.md +113 -141
- package/dist/app.d.ts +0 -6
- package/dist/app.js +0 -307
- package/dist/cli.d.ts +0 -2
- package/dist/commands/build.d.ts +0 -12
- package/dist/commands/deploy.d.ts +0 -16
- package/dist/commands/dev.d.ts +0 -16
- package/dist/commands/index.d.ts +0 -4
- package/dist/commands/info.d.ts +0 -2
- package/dist/commands/setup-signing.d.ts +0 -2
- package/dist/commands/sign.d.ts +0 -14
- package/dist/commands/types.d.ts +0 -18
- package/dist/commands/watch.d.ts +0 -2
- package/dist/components/AnimatedLogo.d.ts +0 -10
- package/dist/components/AuthLoginScreen.d.ts +0 -21
- package/dist/components/DevPropertiesForm.d.ts +0 -10
- package/dist/components/DevPropertiesForm.js +0 -210
- package/dist/components/InfoScreen.d.ts +0 -7
- package/dist/components/InfoScreen.js +0 -14
- package/dist/components/KeychainPasswordChoice.d.ts +0 -8
- package/dist/components/KeychainPasswordChoice.js +0 -30
- package/dist/components/MainMenu.d.ts +0 -7
- package/dist/components/MainMenu.js +0 -83
- package/dist/components/PasswordInput.d.ts +0 -10
- package/dist/components/ProcessOutput.d.ts +0 -6
- package/dist/components/ProcessOutput.js +0 -30
- package/dist/components/SetupFlow.d.ts +0 -8
- package/dist/components/SetupFlow.js +0 -233
- package/dist/components/SigningPropertiesForm.d.ts +0 -7
- package/dist/components/SigningPropertiesForm.js +0 -38
- package/dist/components/StatusIndicator.d.ts +0 -8
- package/dist/components/TextInput.d.ts +0 -10
- package/dist/components/TextInput.js +0 -29
- package/dist/components/WelcomeScreen.d.ts +0 -14
- package/dist/types/index.d.ts +0 -284
- package/dist/utils/branding.d.ts +0 -28
- package/dist/utils/config.d.ts +0 -17
- package/dist/utils/jsonc.d.ts +0 -19
- package/dist/utils/keychain.d.ts +0 -15
- package/dist/utils/oauth2-auth.d.ts +0 -27
- package/dist/utils/password-prompt.d.ts +0 -14
- package/dist/utils/process-runner.d.ts +0 -22
- package/dist/utils/project-detection.d.ts +0 -151
- package/dist/utils/session-cookie-auth.d.ts +0 -34
- package/dist/utils/signing-password.d.ts +0 -12
- package/dist/utils/signing-step.d.ts +0 -15
- package/dist/utils/signing-step.js +0 -16
- package/dist/utils/sitevision-api.d.ts +0 -112
- package/dist/utils/sitevision-scripts-runner.d.ts +0 -83
- package/dist/utils/version-check.d.ts +0 -9
- package/dist/utils/webpack-runner.d.ts +0 -76
- package/dist/utils/zip.d.ts +0 -71
package/dist/commands/dev.js
CHANGED
|
@@ -1,443 +1,114 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
2
|
import React from 'react';
|
|
5
|
-
import { render, Box, Text, useApp, useInput } from 'ink';
|
|
3
|
+
import { render, Box, Text, useApp, useInput, useStdin, useStdout } from 'ink';
|
|
6
4
|
import { StatusIndicator } from '../components/StatusIndicator.js';
|
|
7
|
-
import { WebpackRunner, hasLocalWebpackConfig } from '../utils/webpack-runner.js';
|
|
8
|
-
import { hasSitevisionScripts, runSitevisionScriptsBuild, getDelegatedZipPath, checkSitevisionScriptsCompatibility, } from '../utils/sitevision-scripts-runner.js';
|
|
9
5
|
import { promptPassword, promptYesNo } from '../utils/password-prompt.js';
|
|
10
|
-
import { signApp, deployApp } from '../utils/sitevision-api.js';
|
|
11
6
|
import { setDeployPassword } from '../utils/keychain.js';
|
|
12
7
|
import { resolveSigningPassword } from '../utils/signing-password.js';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
8
|
+
import { startDev, useTasks } from '../utils/tasks.js';
|
|
9
|
+
import { toDeployConfig } from '../utils/workspace.js';
|
|
10
|
+
import { Log } from '../shell/Tabs.js';
|
|
11
|
+
import { say } from '../utils/debug.js';
|
|
12
|
+
/** Standalone `svc dev` / `svc watch`: one task, its log, Ctrl+C or q to stop. */
|
|
13
|
+
export function DevScreen({ project, options }) {
|
|
16
14
|
const { exit } = useApp();
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
15
|
+
const { stdout } = useStdout();
|
|
16
|
+
const tasks = useTasks();
|
|
17
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
|
+
const task = React.useMemo(() => startDev(project, options), []);
|
|
19
|
+
const live = tasks.find(t => t.id === task.id) ?? task;
|
|
20
|
+
const { isRawModeSupported } = useStdin();
|
|
24
21
|
useInput((input, key) => {
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
if (onRetryCredentials && state.status === 'error' && input === 'r') {
|
|
29
|
-
onRetryCredentials();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
const webpackRunnerRef = React.useRef(null);
|
|
33
|
-
const watchersRef = React.useRef([]);
|
|
34
|
-
const debounceTimerRef = React.useRef(null);
|
|
35
|
-
const isBuildingRef = React.useRef(false);
|
|
36
|
-
const pendingRebuildRef = React.useRef(false);
|
|
37
|
-
// Sign (if needed) and deploy an already-built zip, updating UI state.
|
|
38
|
-
const refreshVersion = React.useCallback(() => {
|
|
39
|
-
try {
|
|
40
|
-
const fresh = readManifest(projectRoot)?.manifest.version;
|
|
41
|
-
if (fresh)
|
|
42
|
-
setVersion(fresh);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
// keep last known version
|
|
46
|
-
}
|
|
47
|
-
}, [projectRoot]);
|
|
48
|
-
const signAndDeploy = React.useCallback(async (zipPath, buildTime) => {
|
|
49
|
-
try {
|
|
50
|
-
let deployZipPath = zipPath;
|
|
51
|
-
// Sign if needed
|
|
52
|
-
if (signed && signingCredentials) {
|
|
53
|
-
setState(prev => ({
|
|
54
|
-
...prev,
|
|
55
|
-
status: 'signing',
|
|
56
|
-
message: 'Signing app...',
|
|
57
|
-
}));
|
|
58
|
-
const signedZipPath = getSignedZipPath(projectRoot, manifest);
|
|
59
|
-
const signResult = await signApp(zipPath, signingCredentials, signedZipPath);
|
|
60
|
-
if (!signResult.success) {
|
|
61
|
-
setState(prev => ({
|
|
62
|
-
...prev,
|
|
63
|
-
status: 'error',
|
|
64
|
-
message: `Signing failed: ${signResult.error}`,
|
|
65
|
-
error: signResult.error,
|
|
66
|
-
}));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
deployZipPath = signedZipPath;
|
|
70
|
-
}
|
|
71
|
-
refreshVersion();
|
|
72
|
-
// Watch/build-only mode: stop after building (and signing).
|
|
73
|
-
if (!deploy || !devProperties) {
|
|
74
|
-
setState(prev => ({
|
|
75
|
-
...prev,
|
|
76
|
-
status: 'ready',
|
|
77
|
-
message: signed
|
|
78
|
-
? 'Signed. Watching for changes...'
|
|
79
|
-
: 'Built. Watching for changes...',
|
|
80
|
-
buildCount: prev.buildCount + 1,
|
|
81
|
-
lastBuildTime: buildTime,
|
|
82
|
-
error: undefined,
|
|
83
|
-
}));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Deploy
|
|
87
|
-
setState(prev => ({
|
|
88
|
-
...prev,
|
|
89
|
-
status: 'deploying',
|
|
90
|
-
message: 'Deploying to dev...',
|
|
91
|
-
}));
|
|
92
|
-
const appType = getAppType(manifest);
|
|
93
|
-
const deployResult = await deployApp(deployZipPath, {
|
|
94
|
-
domain: devProperties.domain,
|
|
95
|
-
siteName: devProperties.siteName,
|
|
96
|
-
addonName: devProperties.addonName,
|
|
97
|
-
username: devProperties.username,
|
|
98
|
-
password: devProperties.password,
|
|
99
|
-
useHTTP: devProperties.useHTTPForDevDeploy,
|
|
100
|
-
}, appType, true);
|
|
101
|
-
if (!deployResult.success) {
|
|
102
|
-
setState(prev => ({
|
|
103
|
-
...prev,
|
|
104
|
-
status: 'error',
|
|
105
|
-
message: `Deploy failed: ${deployResult.error}`,
|
|
106
|
-
error: deployResult.error,
|
|
107
|
-
}));
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
// Success - back to watching
|
|
111
|
-
setState(prev => ({
|
|
112
|
-
...prev,
|
|
113
|
-
status: 'ready',
|
|
114
|
-
message: 'Deployed. Watching for changes...',
|
|
115
|
-
buildCount: prev.buildCount + 1,
|
|
116
|
-
lastBuildTime: buildTime,
|
|
117
|
-
error: undefined,
|
|
118
|
-
}));
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
setState(prev => ({
|
|
122
|
-
...prev,
|
|
123
|
-
status: 'error',
|
|
124
|
-
message: error instanceof Error ? error.message : String(error),
|
|
125
|
-
error: error instanceof Error ? error.message : String(error),
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
}, [
|
|
129
|
-
projectRoot,
|
|
130
|
-
manifest,
|
|
131
|
-
devProperties,
|
|
132
|
-
signed,
|
|
133
|
-
deploy,
|
|
134
|
-
signingCredentials,
|
|
135
|
-
refreshVersion,
|
|
136
|
-
]);
|
|
137
|
-
// In-house webpack path: copy static, zip, then sign + deploy.
|
|
138
|
-
const handleBuildComplete = React.useCallback(async (result) => {
|
|
139
|
-
if (!result.success) {
|
|
140
|
-
setState(prev => ({
|
|
141
|
-
...prev,
|
|
142
|
-
status: 'error',
|
|
143
|
-
message: result.errors?.join('\n') || 'Build failed',
|
|
144
|
-
error: result.errors?.join('\n'),
|
|
145
|
-
}));
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
try {
|
|
149
|
-
copyStaticToBuild(projectRoot);
|
|
150
|
-
const appId = getFullAppId(manifest.id);
|
|
151
|
-
await createBuildZip(projectRoot, appId);
|
|
152
|
-
await signAndDeploy(getZipPath(projectRoot, manifest), result.stats?.time);
|
|
153
|
-
}
|
|
154
|
-
catch (error) {
|
|
155
|
-
setState(prev => ({
|
|
156
|
-
...prev,
|
|
157
|
-
status: 'error',
|
|
158
|
-
message: error instanceof Error ? error.message : String(error),
|
|
159
|
-
error: error instanceof Error ? error.message : String(error),
|
|
160
|
-
}));
|
|
161
|
-
}
|
|
162
|
-
}, [projectRoot, manifest, signAndDeploy]);
|
|
163
|
-
// Delegated path: full `sitevision-scripts build` then sign + deploy.
|
|
164
|
-
// Coalesces overlapping triggers so a save mid-build queues one rebuild.
|
|
165
|
-
const runDelegatedBuild = React.useCallback(async () => {
|
|
166
|
-
if (isBuildingRef.current) {
|
|
167
|
-
pendingRebuildRef.current = true;
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
isBuildingRef.current = true;
|
|
171
|
-
const buildOnce = async () => {
|
|
172
|
-
pendingRebuildRef.current = false;
|
|
173
|
-
setState(prev => ({
|
|
174
|
-
...prev,
|
|
175
|
-
status: 'building',
|
|
176
|
-
message: 'Building via sitevision-scripts...',
|
|
177
|
-
}));
|
|
178
|
-
const result = await runSitevisionScriptsBuild(projectRoot);
|
|
179
|
-
if (result.success) {
|
|
180
|
-
await signAndDeploy(getDelegatedZipPath(projectRoot, manifest.id));
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
setState(prev => ({
|
|
184
|
-
...prev,
|
|
185
|
-
status: 'error',
|
|
186
|
-
message: result.error ?? 'Build failed',
|
|
187
|
-
error: `${result.error}\n${result.output.slice(-1000)}`,
|
|
188
|
-
}));
|
|
189
|
-
}
|
|
190
|
-
if (pendingRebuildRef.current) {
|
|
191
|
-
await buildOnce();
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
try {
|
|
195
|
-
await buildOnce();
|
|
196
|
-
}
|
|
197
|
-
finally {
|
|
198
|
-
isBuildingRef.current = false;
|
|
199
|
-
}
|
|
200
|
-
}, [projectRoot, manifest, signAndDeploy]);
|
|
201
|
-
// Watch source files and trigger a delegated rebuild (debounced).
|
|
202
|
-
const startFileWatcher = React.useCallback(() => {
|
|
203
|
-
const targets = [
|
|
204
|
-
'src',
|
|
205
|
-
'static',
|
|
206
|
-
'i18n',
|
|
207
|
-
'resource',
|
|
208
|
-
'config',
|
|
209
|
-
'manifest.json',
|
|
210
|
-
]
|
|
211
|
-
.map(name => path.join(projectRoot, name))
|
|
212
|
-
.filter(target => fs.existsSync(target));
|
|
213
|
-
for (const target of targets) {
|
|
214
|
-
const isDir = fs.statSync(target).isDirectory();
|
|
215
|
-
const watcher = fs.watch(target, { recursive: isDir }, () => {
|
|
216
|
-
if (debounceTimerRef.current) {
|
|
217
|
-
clearTimeout(debounceTimerRef.current);
|
|
218
|
-
}
|
|
219
|
-
debounceTimerRef.current = setTimeout(() => {
|
|
220
|
-
void runDelegatedBuild();
|
|
221
|
-
}, 300);
|
|
222
|
-
});
|
|
223
|
-
watchersRef.current.push(watcher);
|
|
224
|
-
}
|
|
225
|
-
}, [projectRoot, runDelegatedBuild]);
|
|
226
|
-
React.useEffect(() => {
|
|
227
|
-
const isBundled = isBundledApp(manifest);
|
|
228
|
-
async function startWatch() {
|
|
229
|
-
try {
|
|
230
|
-
// Clean build directory
|
|
231
|
-
cleanBuild(projectRoot);
|
|
232
|
-
if (isBundled && !hasLocalWebpackConfig(projectRoot)) {
|
|
233
|
-
// No local webpack config: delegate each build to
|
|
234
|
-
// sitevision-scripts (full rebuild) and watch source files
|
|
235
|
-
// ourselves, keeping the CLI's own sign + deploy flow.
|
|
236
|
-
if (!hasSitevisionScripts(projectRoot)) {
|
|
237
|
-
setState({
|
|
238
|
-
status: 'error',
|
|
239
|
-
message: 'No webpack.config.js found and @sitevision/sitevision-scripts is not installed. Run npm install.',
|
|
240
|
-
buildCount: 0,
|
|
241
|
-
webpackReady: false,
|
|
242
|
-
error: 'No build pipeline available',
|
|
243
|
-
});
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const warning = checkSitevisionScriptsCompatibility(projectRoot).warning;
|
|
247
|
-
setState(prev => ({ ...prev, webpackReady: true, warning }));
|
|
248
|
-
startFileWatcher();
|
|
249
|
-
await runDelegatedBuild();
|
|
250
|
-
}
|
|
251
|
-
else if (isBundled) {
|
|
252
|
-
// Project ships its own webpack config: incremental in-process watch.
|
|
253
|
-
if (!WebpackRunner.isWebpackAvailable(projectRoot)) {
|
|
254
|
-
setState({
|
|
255
|
-
status: 'error',
|
|
256
|
-
message: 'webpack not found. Run npm install.',
|
|
257
|
-
buildCount: 0,
|
|
258
|
-
webpackReady: false,
|
|
259
|
-
error: 'webpack not found',
|
|
260
|
-
});
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
setState(prev => ({
|
|
264
|
-
...prev,
|
|
265
|
-
status: 'building',
|
|
266
|
-
message: 'Starting initial build...',
|
|
267
|
-
}));
|
|
268
|
-
const appType = getAppType(manifest);
|
|
269
|
-
const runner = new WebpackRunner(projectRoot, {
|
|
270
|
-
mode: 'development',
|
|
271
|
-
watch: true,
|
|
272
|
-
cssPrefix: manifest.id,
|
|
273
|
-
restApp: appType === 'rest',
|
|
274
|
-
});
|
|
275
|
-
webpackRunnerRef.current = runner;
|
|
276
|
-
await runner.watch(handleBuildComplete);
|
|
277
|
-
setState(prev => ({
|
|
278
|
-
...prev,
|
|
279
|
-
status: 'watching',
|
|
280
|
-
message: 'Building...',
|
|
281
|
-
webpackReady: true,
|
|
282
|
-
}));
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
// Non-bundled app: just copy and deploy
|
|
286
|
-
setState(prev => ({
|
|
287
|
-
...prev,
|
|
288
|
-
status: 'building',
|
|
289
|
-
message: 'Copying files...',
|
|
290
|
-
}));
|
|
291
|
-
await handleBuildComplete({
|
|
292
|
-
success: true,
|
|
293
|
-
stats: { time: 0, hash: '', assets: [] },
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (error) {
|
|
298
|
-
setState({
|
|
299
|
-
status: 'error',
|
|
300
|
-
message: error instanceof Error ? error.message : String(error),
|
|
301
|
-
buildCount: 0,
|
|
302
|
-
webpackReady: false,
|
|
303
|
-
error: error instanceof Error ? error.message : String(error),
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
startWatch();
|
|
308
|
-
// Cleanup
|
|
309
|
-
return () => {
|
|
310
|
-
if (webpackRunnerRef.current) {
|
|
311
|
-
webpackRunnerRef.current.close().catch(() => { });
|
|
312
|
-
}
|
|
313
|
-
if (debounceTimerRef.current) {
|
|
314
|
-
clearTimeout(debounceTimerRef.current);
|
|
315
|
-
}
|
|
316
|
-
for (const watcher of watchersRef.current) {
|
|
317
|
-
watcher.close();
|
|
318
|
-
}
|
|
319
|
-
watchersRef.current = [];
|
|
320
|
-
};
|
|
321
|
-
}, [
|
|
322
|
-
projectRoot,
|
|
323
|
-
manifest,
|
|
324
|
-
handleBuildComplete,
|
|
325
|
-
runDelegatedBuild,
|
|
326
|
-
startFileWatcher,
|
|
327
|
-
]);
|
|
328
|
-
// Handle Ctrl+C
|
|
329
|
-
React.useEffect(() => {
|
|
330
|
-
const handleExit = () => {
|
|
331
|
-
if (webpackRunnerRef.current) {
|
|
332
|
-
webpackRunnerRef.current.close().catch(() => { });
|
|
333
|
-
}
|
|
334
|
-
for (const watcher of watchersRef.current) {
|
|
335
|
-
watcher.close();
|
|
336
|
-
}
|
|
22
|
+
if (key.escape || input === 'q') {
|
|
23
|
+
live.stop();
|
|
337
24
|
exit();
|
|
338
|
-
};
|
|
339
|
-
process.on('SIGINT', handleExit);
|
|
340
|
-
process.on('SIGTERM', handleExit);
|
|
341
|
-
return () => {
|
|
342
|
-
process.off('SIGINT', handleExit);
|
|
343
|
-
process.off('SIGTERM', handleExit);
|
|
344
|
-
};
|
|
345
|
-
}, [exit]);
|
|
346
|
-
const getStatusType = () => {
|
|
347
|
-
switch (state.status) {
|
|
348
|
-
case 'error':
|
|
349
|
-
return 'error';
|
|
350
|
-
case 'ready':
|
|
351
|
-
return 'success';
|
|
352
|
-
default:
|
|
353
|
-
return 'running';
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
const getStatusLabel = () => {
|
|
357
|
-
switch (state.status) {
|
|
358
|
-
case 'initializing':
|
|
359
|
-
return 'Initializing';
|
|
360
|
-
case 'watching':
|
|
361
|
-
return 'Watching';
|
|
362
|
-
case 'building':
|
|
363
|
-
return 'Building';
|
|
364
|
-
case 'signing':
|
|
365
|
-
return 'Signing';
|
|
366
|
-
case 'deploying':
|
|
367
|
-
return 'Deploying';
|
|
368
|
-
case 'ready':
|
|
369
|
-
return 'Ready';
|
|
370
|
-
case 'error':
|
|
371
|
-
return 'Error';
|
|
372
25
|
}
|
|
26
|
+
},
|
|
27
|
+
// Undefined, not false, on a pipe; and useInput reads undefined as active.
|
|
28
|
+
{ isActive: Boolean(isRawModeSupported) });
|
|
29
|
+
const status = live.status === 'running'
|
|
30
|
+
? live.phase === 'error'
|
|
31
|
+
? 'error'
|
|
32
|
+
: 'running'
|
|
33
|
+
: live.status === 'success'
|
|
34
|
+
? 'success'
|
|
35
|
+
: 'error';
|
|
36
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(StatusIndicator, { status: status, label: live.phase, message: `${live.label} ${live.appName}` }), _jsx(Box, { marginTop: 1, children: _jsx(Log, { task: live, height: (stdout.rows || 24) - 6, scroll: 0, wrap: true }) }), _jsx(Text, { dimColor: true, children: "Press q, Esc or Ctrl+C to stop" })] }));
|
|
37
|
+
}
|
|
38
|
+
/** Resolve signing credentials for signed dev/watch, prompting if needed. */
|
|
39
|
+
export async function resolveSigningForCli(project) {
|
|
40
|
+
if (!project.hasSigningProperties ||
|
|
41
|
+
!project.devProperties?.signingUsername) {
|
|
42
|
+
say('\n\x1b[33mSigning credentials not configured.\x1b[0m');
|
|
43
|
+
say('Run \x1b[36msetup-signing\x1b[0m to configure credentials.\n');
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const signingUsername = project.devProperties.signingUsername;
|
|
48
|
+
const password = await resolveSigningPassword(signingUsername);
|
|
49
|
+
if (!password) {
|
|
50
|
+
say('\x1b[31mError: Password is required for signed mode\x1b[0m');
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
username: signingUsername,
|
|
56
|
+
password,
|
|
57
|
+
certificateName: project.devProperties.certificateName,
|
|
373
58
|
};
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
59
|
+
}
|
|
60
|
+
/** Basic auth without a stored password: ask for it. False when there is none. */
|
|
61
|
+
export async function resolveDeployPasswordForCli(dev) {
|
|
62
|
+
if ((dev.authMethod ?? 'basic') !== 'basic' || dev.password)
|
|
63
|
+
return true;
|
|
64
|
+
const { domain, username } = dev;
|
|
65
|
+
console.log('');
|
|
66
|
+
const password = await promptPassword(`Deploy password for ${username}@${domain}: `);
|
|
67
|
+
if (!password) {
|
|
68
|
+
say('\x1b[31mError: Password is required\x1b[0m');
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
if (await promptYesNo('Save password to OS keychain? (y/N): ')) {
|
|
73
|
+
setDeployPassword(domain, username, password);
|
|
74
|
+
}
|
|
75
|
+
dev.password = password;
|
|
76
|
+
return true;
|
|
377
77
|
}
|
|
378
78
|
export const devCommand = {
|
|
379
79
|
name: 'dev',
|
|
380
80
|
description: 'Start development server with watch mode',
|
|
381
81
|
requiresProject: true,
|
|
382
|
-
flags: {
|
|
383
|
-
signed: {
|
|
384
|
-
type: 'boolean',
|
|
385
|
-
description: 'Use signed mode (sign before each deploy)',
|
|
386
|
-
alias: 's',
|
|
387
|
-
default: false,
|
|
388
|
-
},
|
|
389
|
-
},
|
|
390
82
|
async execute({ project, flags }) {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
83
|
+
const dev = project.devProperties;
|
|
84
|
+
const incomplete = toDeployConfig(dev);
|
|
85
|
+
if (!dev || 'error' in incomplete) {
|
|
86
|
+
say(`\n\x1b[33m${'error' in incomplete ? incomplete.error : ''}\x1b[0m\n`);
|
|
87
|
+
process.exitCode = 1;
|
|
395
88
|
return;
|
|
396
89
|
}
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
if ((
|
|
400
|
-
|
|
90
|
+
// The standalone command only prompts for a basic password; OAuth2/cookie
|
|
91
|
+
// logins are interactive and live in the shell (`svc`) or `svc deploy`.
|
|
92
|
+
if ((dev.authMethod ?? 'basic') !== 'basic' &&
|
|
93
|
+
!dev.accessToken &&
|
|
94
|
+
!dev.sessionCookie) {
|
|
95
|
+
say('\n\x1b[33mNo token/cookie available. Run `svc` and use Dev from the shell, or set SITEVISION_ACCESS_TOKEN / SITEVISION_SESSION_COOKIE.\x1b[0m\n');
|
|
96
|
+
process.exitCode = 1;
|
|
401
97
|
return;
|
|
402
98
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const { domain, username } = project.devProperties;
|
|
406
|
-
console.log('');
|
|
407
|
-
const pw = await promptPassword(`Deploy password for ${username}@${domain}: `);
|
|
408
|
-
if (!pw) {
|
|
409
|
-
console.log('\x1b[31mError: Password is required\x1b[0m');
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
const remember = await promptYesNo('Save password to OS keychain? (y/N): ');
|
|
413
|
-
if (remember && domain && username) {
|
|
414
|
-
setDeployPassword(domain, username, pw);
|
|
415
|
-
}
|
|
416
|
-
project.devProperties.password = pw;
|
|
417
|
-
}
|
|
418
|
-
const signed = Boolean(flags['signed']);
|
|
99
|
+
if (!(await resolveDeployPasswordForCli(dev)))
|
|
100
|
+
return;
|
|
419
101
|
let signingCredentials;
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (!
|
|
423
|
-
!project.devProperties.signingUsername) {
|
|
424
|
-
console.log('\n\x1b[33mSigning credentials not configured.\x1b[0m');
|
|
425
|
-
console.log('Run \x1b[36msetup-signing\x1b[0m to configure credentials.\n');
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
const signingUsername = project.devProperties.signingUsername;
|
|
429
|
-
const password = await resolveSigningPassword(signingUsername);
|
|
430
|
-
if (!password) {
|
|
431
|
-
console.log('\x1b[31mError: Password is required for signed mode\x1b[0m');
|
|
102
|
+
if (flags['signed']) {
|
|
103
|
+
signingCredentials = await resolveSigningForCli(project);
|
|
104
|
+
if (!signingCredentials)
|
|
432
105
|
return;
|
|
433
|
-
}
|
|
434
|
-
signingCredentials = {
|
|
435
|
-
username: signingUsername,
|
|
436
|
-
password,
|
|
437
|
-
certificateName: project.devProperties.certificateName,
|
|
438
|
-
};
|
|
439
106
|
}
|
|
440
|
-
const { waitUntilExit } = render(_jsx(DevScreen, {
|
|
107
|
+
const { waitUntilExit } = render(_jsx(DevScreen, { project: project, options: {
|
|
108
|
+
deploy: true,
|
|
109
|
+
signingCredentials,
|
|
110
|
+
deployConfig: { ...incomplete.config, password: dev.password },
|
|
111
|
+
} }));
|
|
441
112
|
await waitUntilExit();
|
|
442
113
|
},
|
|
443
114
|
};
|
package/dist/commands/info.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Box, Text } from 'ink';
|
|
|
4
4
|
import { getAppType, localizedText } from '../utils/project-detection.js';
|
|
5
5
|
function InfoScreen({ project }) {
|
|
6
6
|
const appType = getAppType(project.manifest);
|
|
7
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Sitevision Project Information" }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Name: " }), _jsx(Text, { children: localizedText(project.manifest.name) })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "ID: " }), _jsx(Text, { children: project.manifest.id })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Version: " }), _jsx(Text, { children: project.manifest.version })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Type: " }), _jsx(Text, { color: "green", children: project.manifest.type }), _jsxs(Text, { dimColor: true, children: [" (", appType, ")"] })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Bundled: " }), _jsx(Text, { children: project.manifest.bundled ? 'Yes' : 'No' })] })] }), project.hasDevProperties && project.devProperties && (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Development Configuration" }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Domain: " }), _jsx(Text, { children: project.devProperties.domain })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Site: " }), _jsx(Text, { children: project.devProperties.siteName })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Addon: " }), _jsx(Text, { children: project.devProperties.addonName })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Username: " }), _jsx(Text, { children: project.devProperties.username })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Use HTTP: " }), _jsx(Text, { children: project.devProperties.useHTTPForDevDeploy ? 'Yes' : 'No' })] })] })] })), !project.hasDevProperties && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "yellow", children: ["\u26A0 No dev properties found. Run", ' ', _jsx(Text, { bold: true, children: "
|
|
7
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Sitevision Project Information" }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Name: " }), _jsx(Text, { children: localizedText(project.manifest.name) })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "ID: " }), _jsx(Text, { children: project.manifest.id })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Version: " }), _jsx(Text, { children: project.manifest.version })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Type: " }), _jsx(Text, { color: "green", children: project.manifest.type }), _jsxs(Text, { dimColor: true, children: [" (", appType, ")"] })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Bundled: " }), _jsx(Text, { children: project.manifest.bundled ? 'Yes' : 'No' })] })] }), project.hasDevProperties && project.devProperties && (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: "Development Configuration" }) }), _jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Domain: " }), _jsx(Text, { children: project.devProperties.domain })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Site: " }), _jsx(Text, { children: project.devProperties.siteName })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Addon: " }), _jsx(Text, { children: project.devProperties.addonName })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Username: " }), _jsx(Text, { children: project.devProperties.username })] }), _jsxs(Box, { children: [_jsx(Text, { bold: true, children: "Use HTTP: " }), _jsx(Text, { children: project.devProperties.useHTTPForDevDeploy ? 'Yes' : 'No' })] })] })] })), !project.hasDevProperties && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "yellow", children: ["\u26A0 No dev properties found. Run ", _jsx(Text, { bold: true, children: "svc" }), " and press", ' ', _jsx(Text, { bold: true, children: "e" }), " to configure."] }) })), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { bold: true, children: "Project Root: " }), _jsx(Text, { dimColor: true, children: project.root })] })] }));
|
|
8
8
|
}
|
|
9
9
|
export const infoCommand = {
|
|
10
10
|
name: 'info',
|