sitevision-cli 0.4.0-beta.0 → 0.4.0-beta.2
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/app.js +53 -15
- package/dist/commands/dev.js +3 -16
- package/dist/commands/sign.js +2 -18
- package/dist/components/KeychainPasswordChoice.d.ts +8 -0
- package/dist/components/KeychainPasswordChoice.js +30 -0
- package/dist/components/PasswordInput.d.ts +3 -1
- package/dist/components/PasswordInput.js +3 -3
- package/dist/utils/password-prompt.d.ts +3 -2
- package/dist/utils/password-prompt.js +10 -3
- package/dist/utils/signing-password.d.ts +12 -0
- package/dist/utils/signing-password.js +36 -0
- package/dist/utils/signing-step.d.ts +15 -0
- package/dist/utils/signing-step.js +16 -0
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -1,20 +1,48 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
3
|
import { MainMenu } from './components/MainMenu.js';
|
|
4
4
|
import { InfoScreen } from './components/InfoScreen.js';
|
|
5
5
|
import { SetupFlow } from './components/SetupFlow.js';
|
|
6
6
|
import { PasswordInput } from './components/PasswordInput.js';
|
|
7
|
+
import { KeychainPasswordChoice } from './components/KeychainPasswordChoice.js';
|
|
8
|
+
import { decideSigningStep } from './utils/signing-step.js';
|
|
7
9
|
import { DevScreen } from './commands/dev.js';
|
|
8
10
|
import { BuildScreen } from './commands/build.js';
|
|
9
11
|
import { DeployScreen } from './commands/deploy.js';
|
|
10
12
|
import { SignScreen } from './commands/sign.js';
|
|
11
13
|
import { SigningPropertiesForm } from './components/SigningPropertiesForm.js';
|
|
12
|
-
import { setDeployPassword as saveDeployPassword, setSigningPassword as saveSigningPassword, } from './utils/keychain.js';
|
|
14
|
+
import { getSigningPassword, setDeployPassword as saveDeployPassword, setSigningPassword as saveSigningPassword, } from './utils/keychain.js';
|
|
13
15
|
export default function App({ project }) {
|
|
14
16
|
const [state, setState] = useState('setup');
|
|
15
17
|
const [currentCommand, setCurrentCommand] = useState('');
|
|
16
18
|
const [signingPassword, setSigningPassword] = useState('');
|
|
17
19
|
const [devPassword, setDevPassword] = useState('');
|
|
20
|
+
// When true, skip the keychain "use saved / enter new" choice and go straight
|
|
21
|
+
// to manual entry (e.g. the saved password just failed and we're retrying).
|
|
22
|
+
const [signingRetry, setSigningRetry] = useState(false);
|
|
23
|
+
// Read the saved signing password from the keychain once (keychain access is
|
|
24
|
+
// slow and this component re-renders frequently).
|
|
25
|
+
const signingUsername = project.devProperties?.signingUsername;
|
|
26
|
+
const storedSigningPassword = useMemo(() => (signingUsername ? getSigningPassword(signingUsername) : null), [signingUsername]);
|
|
27
|
+
// Decide the next step once a signing password is needed: proceed if we already
|
|
28
|
+
// have one this session, offer the keychain choice if one is saved, otherwise
|
|
29
|
+
// prompt for manual entry.
|
|
30
|
+
const routeToSigningStep = (command = currentCommand) => {
|
|
31
|
+
const step = decideSigningStep({
|
|
32
|
+
hasSessionPassword: Boolean(signingPassword),
|
|
33
|
+
hasStoredPassword: Boolean(storedSigningPassword),
|
|
34
|
+
isRetry: signingRetry,
|
|
35
|
+
});
|
|
36
|
+
if (step === 'proceed') {
|
|
37
|
+
setState(command === 'dev-signed' ? 'dev' : 'sign');
|
|
38
|
+
}
|
|
39
|
+
else if (step === 'choice') {
|
|
40
|
+
setState('signing-password-choice');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
setState('signing-password-input');
|
|
44
|
+
}
|
|
45
|
+
};
|
|
18
46
|
// Check if dev password is available (either from file or session)
|
|
19
47
|
const hasDevPassword = Boolean(project.devProperties?.password || devPassword);
|
|
20
48
|
// Get effective dev properties with session password if needed
|
|
@@ -35,8 +63,8 @@ export default function App({ project }) {
|
|
|
35
63
|
}
|
|
36
64
|
// Continue to the intended command
|
|
37
65
|
if (currentCommand === 'dev' || currentCommand === 'dev-signed') {
|
|
38
|
-
if (currentCommand === 'dev-signed'
|
|
39
|
-
|
|
66
|
+
if (currentCommand === 'dev-signed') {
|
|
67
|
+
routeToSigningStep();
|
|
40
68
|
}
|
|
41
69
|
else {
|
|
42
70
|
setState('dev');
|
|
@@ -46,6 +74,15 @@ export default function App({ project }) {
|
|
|
46
74
|
setState('deploy');
|
|
47
75
|
}
|
|
48
76
|
};
|
|
77
|
+
const handleUseSavedSigning = () => {
|
|
78
|
+
if (storedSigningPassword) {
|
|
79
|
+
setSigningPassword(storedSigningPassword);
|
|
80
|
+
}
|
|
81
|
+
setState(currentCommand === 'dev-signed' ? 'dev' : 'sign');
|
|
82
|
+
};
|
|
83
|
+
const handleEnterNewSigning = () => {
|
|
84
|
+
setState('signing-password-input');
|
|
85
|
+
};
|
|
49
86
|
const handleSigningPasswordSubmit = (password, remember) => {
|
|
50
87
|
setSigningPassword(password);
|
|
51
88
|
if (remember && project.devProperties?.signingUsername && password) {
|
|
@@ -60,6 +97,8 @@ export default function App({ project }) {
|
|
|
60
97
|
};
|
|
61
98
|
const handleCommandSelect = (command) => {
|
|
62
99
|
setCurrentCommand(command);
|
|
100
|
+
// Fresh selection from the menu — re-offer the saved keychain password.
|
|
101
|
+
setSigningRetry(false);
|
|
63
102
|
switch (command) {
|
|
64
103
|
case 'info':
|
|
65
104
|
setState('info');
|
|
@@ -92,11 +131,8 @@ export default function App({ project }) {
|
|
|
92
131
|
if (!hasDevPassword) {
|
|
93
132
|
setState('dev-password-input');
|
|
94
133
|
}
|
|
95
|
-
else if (!signingPassword) {
|
|
96
|
-
setState('signing-password-input');
|
|
97
|
-
}
|
|
98
134
|
else {
|
|
99
|
-
|
|
135
|
+
routeToSigningStep(command);
|
|
100
136
|
}
|
|
101
137
|
break;
|
|
102
138
|
case 'sign':
|
|
@@ -108,12 +144,7 @@ export default function App({ project }) {
|
|
|
108
144
|
console.log('\x1b[31mSigning credentials not configured. Run svc setup-signing first.\x1b[0m');
|
|
109
145
|
return;
|
|
110
146
|
}
|
|
111
|
-
|
|
112
|
-
setState('sign');
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
setState('signing-password-input');
|
|
116
|
-
}
|
|
147
|
+
routeToSigningStep(command);
|
|
117
148
|
break;
|
|
118
149
|
case 'build':
|
|
119
150
|
setState('build');
|
|
@@ -146,8 +177,13 @@ export default function App({ project }) {
|
|
|
146
177
|
if (state === 'dev-password-input') {
|
|
147
178
|
return (_jsx(PasswordInput, { label: "Enter Development Password (usually Sitevision Cloud Password)", showRememberOption: Boolean(project.devProperties?.domain && project.devProperties?.username), onSubmit: handleDevPasswordSubmit, onCancel: () => setState('menu') }, "dev-password"));
|
|
148
179
|
}
|
|
180
|
+
if (state === 'signing-password-choice') {
|
|
181
|
+
return (_jsx(KeychainPasswordChoice, { onUseSaved: handleUseSavedSigning, onEnterNew: handleEnterNewSigning, onCancel: () => setState('menu') }, "signing-password-choice"));
|
|
182
|
+
}
|
|
149
183
|
if (state === 'signing-password-input') {
|
|
150
|
-
return (_jsx(PasswordInput, { label: "Enter Signing Password (developer.sitevision.se)", showRememberOption: Boolean(project.devProperties?.signingUsername),
|
|
184
|
+
return (_jsx(PasswordInput, { label: "Enter Signing Password (developer.sitevision.se)", showRememberOption: Boolean(project.devProperties?.signingUsername), defaultRemember: Boolean(storedSigningPassword), rememberLabel: storedSigningPassword
|
|
185
|
+
? 'Update saved password in OS keychain: '
|
|
186
|
+
: 'Save to OS keychain: ', onSubmit: handleSigningPasswordSubmit, onCancel: () => setState('menu') }, "signing-password"));
|
|
151
187
|
}
|
|
152
188
|
if (state === 'dev') {
|
|
153
189
|
return (_jsx(DevScreen, { projectRoot: project.root, manifest: project.manifest, devProperties: getEffectiveDevProperties(), signed: currentCommand === 'dev-signed', onBack: () => setState('menu'), onRetryCredentials: () => {
|
|
@@ -156,6 +192,8 @@ export default function App({ project }) {
|
|
|
156
192
|
project.devProperties.password = undefined;
|
|
157
193
|
if (currentCommand === 'dev-signed') {
|
|
158
194
|
setSigningPassword('');
|
|
195
|
+
// The saved password may be what failed — don't re-offer it.
|
|
196
|
+
setSigningRetry(true);
|
|
159
197
|
}
|
|
160
198
|
setState('dev-password-input');
|
|
161
199
|
}, signingCredentials: currentCommand === 'dev-signed' &&
|
package/dist/commands/dev.js
CHANGED
|
@@ -5,7 +5,8 @@ import { StatusIndicator } from '../components/StatusIndicator.js';
|
|
|
5
5
|
import { WebpackRunner } from '../utils/webpack-runner.js';
|
|
6
6
|
import { promptPassword, promptYesNo } from '../utils/password-prompt.js';
|
|
7
7
|
import { signApp, deployApp } from '../utils/sitevision-api.js';
|
|
8
|
-
import {
|
|
8
|
+
import { setDeployPassword } from '../utils/keychain.js';
|
|
9
|
+
import { resolveSigningPassword } from '../utils/signing-password.js';
|
|
9
10
|
import { copyStaticToBuild, createBuildZip, cleanBuild } from '../utils/zip.js';
|
|
10
11
|
import { isBundledApp, getAppType, getFullAppId, getZipPath, getSignedZipPath, } from '../utils/project-detection.js';
|
|
11
12
|
export function DevScreen({ projectRoot, manifest, devProperties, signed, signingCredentials, onBack, onRetryCredentials, }) {
|
|
@@ -268,25 +269,11 @@ export const devCommand = {
|
|
|
268
269
|
return;
|
|
269
270
|
}
|
|
270
271
|
const signingUsername = project.devProperties.signingUsername;
|
|
271
|
-
|
|
272
|
-
process.env['SITEVISION_SIGNING_PASSWORD'] ||
|
|
273
|
-
'';
|
|
274
|
-
let promptedManually = false;
|
|
275
|
-
if (!password) {
|
|
276
|
-
console.log('');
|
|
277
|
-
password = await promptPassword('Signing password (developer.sitevision.se): ');
|
|
278
|
-
promptedManually = true;
|
|
279
|
-
}
|
|
272
|
+
const password = await resolveSigningPassword(signingUsername);
|
|
280
273
|
if (!password) {
|
|
281
274
|
console.log('\x1b[31mError: Password is required for signed mode\x1b[0m');
|
|
282
275
|
return;
|
|
283
276
|
}
|
|
284
|
-
if (promptedManually) {
|
|
285
|
-
const remember = await promptYesNo('Save password to OS keychain? (y/N): ');
|
|
286
|
-
if (remember) {
|
|
287
|
-
setSigningPassword(signingUsername, password);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
277
|
signingCredentials = {
|
|
291
278
|
username: signingUsername,
|
|
292
279
|
password,
|
package/dist/commands/sign.js
CHANGED
|
@@ -3,8 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import { render, Box, Text, useInput } from 'ink';
|
|
4
4
|
import { StatusIndicator } from '../components/StatusIndicator.js';
|
|
5
5
|
import { signApp } from '../utils/sitevision-api.js';
|
|
6
|
-
import {
|
|
7
|
-
import { getSigningPassword, setSigningPassword } from '../utils/keychain.js';
|
|
6
|
+
import { resolveSigningPassword } from '../utils/signing-password.js';
|
|
8
7
|
import { getZipPath, getSignedZipPath } from '../utils/project-detection.js';
|
|
9
8
|
import { formatFileSize, getZipSize, zipExists } from '../utils/zip.js';
|
|
10
9
|
export function SignScreen({ projectRoot, manifest, devProperties, password, onBack, onRetryCredentials, }) {
|
|
@@ -84,26 +83,11 @@ export const signCommand = {
|
|
|
84
83
|
return;
|
|
85
84
|
}
|
|
86
85
|
const signingUsername = project.devProperties.signingUsername;
|
|
87
|
-
|
|
88
|
-
let password = getSigningPassword(signingUsername) ||
|
|
89
|
-
process.env['SITEVISION_SIGNING_PASSWORD'] ||
|
|
90
|
-
'';
|
|
91
|
-
let promptedManually = false;
|
|
92
|
-
if (!password) {
|
|
93
|
-
console.log('');
|
|
94
|
-
password = await promptPassword('Signing password (developer.sitevision.se): ');
|
|
95
|
-
promptedManually = true;
|
|
96
|
-
}
|
|
86
|
+
const password = await resolveSigningPassword(signingUsername);
|
|
97
87
|
if (!password) {
|
|
98
88
|
console.log('\x1b[31mError: Password is required\x1b[0m');
|
|
99
89
|
return;
|
|
100
90
|
}
|
|
101
|
-
if (promptedManually) {
|
|
102
|
-
const remember = await promptYesNo('Save password to OS keychain? (y/N): ');
|
|
103
|
-
if (remember) {
|
|
104
|
-
setSigningPassword(signingUsername, password);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
91
|
const { waitUntilExit } = render(_jsx(SignScreen, { projectRoot: project.root, manifest: project.manifest, devProperties: project.devProperties, password: password }));
|
|
108
92
|
await waitUntilExit();
|
|
109
93
|
},
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
const OPTIONS = [
|
|
5
|
+
{ label: 'Use saved password from keychain', value: 'saved' },
|
|
6
|
+
{ label: 'Enter a new password', value: 'new' },
|
|
7
|
+
];
|
|
8
|
+
export function KeychainPasswordChoice({ label = 'A signing password is saved in your OS keychain.', onUseSaved, onEnterNew, onCancel, }) {
|
|
9
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
10
|
+
useInput((_input, key) => {
|
|
11
|
+
if (key.upArrow) {
|
|
12
|
+
setSelectedIndex(prev => (prev === 0 ? OPTIONS.length - 1 : prev - 1));
|
|
13
|
+
}
|
|
14
|
+
else if (key.downArrow) {
|
|
15
|
+
setSelectedIndex(prev => (prev === OPTIONS.length - 1 ? 0 : prev + 1));
|
|
16
|
+
}
|
|
17
|
+
else if (key.return) {
|
|
18
|
+
if (selectedIndex === 0) {
|
|
19
|
+
onUseSaved();
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
onEnterNew();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
else if (key.escape) {
|
|
26
|
+
onCancel();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: label }) }), OPTIONS.map((option, index) => (_jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', option.label] }, option.value))), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "\u2191/\u2193 to move, Enter to select, Esc to cancel" }) })] }));
|
|
30
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
interface Props {
|
|
2
2
|
label?: string;
|
|
3
3
|
showRememberOption?: boolean;
|
|
4
|
+
defaultRemember?: boolean;
|
|
5
|
+
rememberLabel?: string;
|
|
4
6
|
onSubmit: (password: string, remember: boolean) => void;
|
|
5
7
|
onCancel: () => void;
|
|
6
8
|
}
|
|
7
|
-
export declare function PasswordInput({ label, showRememberOption, onSubmit, onCancel, }: Props): import("react").JSX.Element;
|
|
9
|
+
export declare function PasswordInput({ label, showRememberOption, defaultRemember, rememberLabel, onSubmit, onCancel, }: Props): import("react").JSX.Element;
|
|
8
10
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { Box, Text, useInput } from 'ink';
|
|
4
|
-
export function PasswordInput({ label = 'Enter Signing Password', showRememberOption = false, onSubmit, onCancel, }) {
|
|
4
|
+
export function PasswordInput({ label = 'Enter Signing Password', showRememberOption = false, defaultRemember = false, rememberLabel = 'Save to OS keychain: ', onSubmit, onCancel, }) {
|
|
5
5
|
const [password, setPassword] = useState('');
|
|
6
|
-
const [remember, setRemember] = useState(
|
|
6
|
+
const [remember, setRemember] = useState(defaultRemember);
|
|
7
7
|
useInput((input, key) => {
|
|
8
8
|
if (key.return) {
|
|
9
9
|
onSubmit(password, remember);
|
|
@@ -26,5 +26,5 @@ export function PasswordInput({ label = 'Enter Signing Password', showRememberOp
|
|
|
26
26
|
setPassword(prev => prev + input);
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: label }) }), _jsx(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: '*'.repeat(password.length) }) }), showRememberOption && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children:
|
|
29
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "cyan", children: label }) }), _jsx(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: '*'.repeat(password.length) }) }), showRememberOption && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { dimColor: true, children: rememberLabel }), _jsxs(Text, { color: remember ? 'green' : 'gray', children: ["[", remember ? 'x' : ' ', "]"] }), _jsx(Text, { dimColor: true, children: " (Tab to toggle)" })] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press Enter to submit, Esc to cancel" }) })] }));
|
|
30
30
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prompt for a yes/no answer. Returns true for y/Y
|
|
2
|
+
* Prompt for a yes/no answer. Returns true for y/Y.
|
|
3
|
+
* Pressing Enter (empty answer) returns `defaultYes` (default: false).
|
|
3
4
|
*/
|
|
4
|
-
export declare function promptYesNo(prompt: string): Promise<boolean>;
|
|
5
|
+
export declare function promptYesNo(prompt: string, defaultYes?: boolean): Promise<boolean>;
|
|
5
6
|
/**
|
|
6
7
|
* Prompt for password input with masked display
|
|
7
8
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prompt for a yes/no answer. Returns true for y/Y
|
|
2
|
+
* Prompt for a yes/no answer. Returns true for y/Y.
|
|
3
|
+
* Pressing Enter (empty answer) returns `defaultYes` (default: false).
|
|
3
4
|
*/
|
|
4
|
-
export function promptYesNo(prompt) {
|
|
5
|
+
export function promptYesNo(prompt, defaultYes = false) {
|
|
5
6
|
return new Promise(resolve => {
|
|
6
7
|
process.stdout.write(prompt);
|
|
7
8
|
const stdin = process.stdin;
|
|
@@ -14,9 +15,15 @@ export function promptYesNo(prompt) {
|
|
|
14
15
|
stdin.removeListener('data', onData);
|
|
15
16
|
stdin.pause();
|
|
16
17
|
process.stdout.write(`${char}\n`);
|
|
17
|
-
|
|
18
|
+
const charCode = char.charCodeAt(0);
|
|
19
|
+
if (charCode === 3) {
|
|
18
20
|
process.exit();
|
|
19
21
|
}
|
|
22
|
+
// Enter (CR/LF) or empty input → use the default
|
|
23
|
+
if (char === '' || charCode === 13 || charCode === 10) {
|
|
24
|
+
resolve(defaultYes);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
20
27
|
resolve(char === 'y' || char === 'Y');
|
|
21
28
|
};
|
|
22
29
|
stdin.on('data', onData);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the signing password for the given user.
|
|
3
|
+
*
|
|
4
|
+
* Priority:
|
|
5
|
+
* 1. `SITEVISION_SIGNING_PASSWORD` env var (non-interactive override, no prompts).
|
|
6
|
+
* 2. A password saved in the OS keychain — the user is asked whether to use it
|
|
7
|
+
* or set a new one. Choosing "new" optionally updates the saved password.
|
|
8
|
+
* 3. An interactive prompt — optionally saved to the keychain.
|
|
9
|
+
*
|
|
10
|
+
* Returns an empty string if no password could be obtained.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveSigningPassword(signingUsername: string): Promise<string>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getSigningPassword, setSigningPassword } from './keychain.js';
|
|
2
|
+
import { promptPassword, promptYesNo } from './password-prompt.js';
|
|
3
|
+
const SIGNING_PROMPT = 'Signing password (developer.sitevision.se): ';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the signing password for the given user.
|
|
6
|
+
*
|
|
7
|
+
* Priority:
|
|
8
|
+
* 1. `SITEVISION_SIGNING_PASSWORD` env var (non-interactive override, no prompts).
|
|
9
|
+
* 2. A password saved in the OS keychain — the user is asked whether to use it
|
|
10
|
+
* or set a new one. Choosing "new" optionally updates the saved password.
|
|
11
|
+
* 3. An interactive prompt — optionally saved to the keychain.
|
|
12
|
+
*
|
|
13
|
+
* Returns an empty string if no password could be obtained.
|
|
14
|
+
*/
|
|
15
|
+
export async function resolveSigningPassword(signingUsername) {
|
|
16
|
+
const envPassword = process.env['SITEVISION_SIGNING_PASSWORD'];
|
|
17
|
+
if (envPassword)
|
|
18
|
+
return envPassword;
|
|
19
|
+
const stored = getSigningPassword(signingUsername);
|
|
20
|
+
if (stored) {
|
|
21
|
+
const useStored = await promptYesNo('Use saved signing password from keychain? (Y/n): ', true);
|
|
22
|
+
if (useStored)
|
|
23
|
+
return stored;
|
|
24
|
+
}
|
|
25
|
+
console.log('');
|
|
26
|
+
const password = await promptPassword(SIGNING_PROMPT);
|
|
27
|
+
if (!password)
|
|
28
|
+
return '';
|
|
29
|
+
const remember = await promptYesNo(stored
|
|
30
|
+
? 'Update saved password in OS keychain? (y/N): '
|
|
31
|
+
: 'Save password to OS keychain? (y/N): ');
|
|
32
|
+
if (remember) {
|
|
33
|
+
setSigningPassword(signingUsername, password);
|
|
34
|
+
}
|
|
35
|
+
return password;
|
|
36
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type SigningStep = 'proceed' | 'choice' | 'input';
|
|
2
|
+
/**
|
|
3
|
+
* Decide what to do when a signing password is needed.
|
|
4
|
+
*
|
|
5
|
+
* - `proceed`: a password is already available this session — use it.
|
|
6
|
+
* - `choice`: a password is saved in the keychain — ask whether to use it or
|
|
7
|
+
* enter a new one.
|
|
8
|
+
* - `input`: prompt for a password (nothing saved, or a saved one just failed
|
|
9
|
+
* and we're retrying).
|
|
10
|
+
*/
|
|
11
|
+
export declare function decideSigningStep(options: {
|
|
12
|
+
hasSessionPassword: boolean;
|
|
13
|
+
hasStoredPassword: boolean;
|
|
14
|
+
isRetry: boolean;
|
|
15
|
+
}): SigningStep;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide what to do when a signing password is needed.
|
|
3
|
+
*
|
|
4
|
+
* - `proceed`: a password is already available this session — use it.
|
|
5
|
+
* - `choice`: a password is saved in the keychain — ask whether to use it or
|
|
6
|
+
* enter a new one.
|
|
7
|
+
* - `input`: prompt for a password (nothing saved, or a saved one just failed
|
|
8
|
+
* and we're retrying).
|
|
9
|
+
*/
|
|
10
|
+
export function decideSigningStep(options) {
|
|
11
|
+
if (options.hasSessionPassword)
|
|
12
|
+
return 'proceed';
|
|
13
|
+
if (options.hasStoredPassword && !options.isRetry)
|
|
14
|
+
return 'choice';
|
|
15
|
+
return 'input';
|
|
16
|
+
}
|