octo-dev 0.7.1 → 0.7.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/package.json +1 -1
- package/src/cli/index.ts +1 -1
- package/src/shared/git-auth.ts +4 -4
- package/src/shared/prompt.ts +41 -0
- package/src/shared/sync.ts +1 -1
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
package/src/shared/git-auth.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { askSecret } from './prompt.js';
|
|
2
2
|
|
|
3
3
|
let cachedToken: string | undefined;
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Acquires a GitHub Personal Access Token for git HTTPS operations.
|
|
7
|
-
* Prompts the user once and caches in memory for the process lifetime.
|
|
8
|
-
* The token is never persisted to disk.
|
|
7
|
+
* Prompts the user once (input hidden) and caches in memory for the process lifetime.
|
|
8
|
+
* The token is never persisted to disk or echoed to the terminal.
|
|
9
9
|
*
|
|
10
10
|
* @returns The PAT string, or undefined if the user provides empty input (skip).
|
|
11
11
|
*/
|
|
12
12
|
export async function acquireGitToken(): Promise<string | undefined> {
|
|
13
13
|
if (cachedToken) return cachedToken;
|
|
14
|
-
const input = await
|
|
14
|
+
const input = await askSecret('GitHub token (PAT): ');
|
|
15
15
|
cachedToken = input || undefined;
|
|
16
16
|
return cachedToken;
|
|
17
17
|
}
|
package/src/shared/prompt.ts
CHANGED
|
@@ -16,6 +16,47 @@ export function ask(message: string): Promise<string> {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Prompts the user for sensitive input (e.g. tokens, passwords).
|
|
21
|
+
* Input is not echoed to the terminal.
|
|
22
|
+
*
|
|
23
|
+
* @param message - The prompt message displayed to the user.
|
|
24
|
+
* @returns The trimmed secret string.
|
|
25
|
+
*/
|
|
26
|
+
export function askSecret(message: string): Promise<string> {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
process.stdout.write(message);
|
|
29
|
+
|
|
30
|
+
const stdin = process.stdin;
|
|
31
|
+
const wasRaw = stdin.isRaw;
|
|
32
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
33
|
+
stdin.resume();
|
|
34
|
+
stdin.setEncoding('utf-8');
|
|
35
|
+
|
|
36
|
+
let input = '';
|
|
37
|
+
|
|
38
|
+
const onData = (char: string) => {
|
|
39
|
+
if (char === '\n' || char === '\r') {
|
|
40
|
+
stdin.removeListener('data', onData);
|
|
41
|
+
if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);
|
|
42
|
+
stdin.pause();
|
|
43
|
+
process.stdout.write('\n');
|
|
44
|
+
resolve(input.trim());
|
|
45
|
+
} else if (char === '\u0003') {
|
|
46
|
+
// Ctrl+C
|
|
47
|
+
process.exit(130);
|
|
48
|
+
} else if (char === '\u007F' || char === '\b') {
|
|
49
|
+
// Backspace
|
|
50
|
+
input = input.slice(0, -1);
|
|
51
|
+
} else {
|
|
52
|
+
input += char;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
stdin.on('data', onData);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
19
60
|
/**
|
|
20
61
|
* Prompts the user with a yes/no question via stdin.
|
|
21
62
|
* Accepts 'y', 'Y', 's', 'S' as affirmative responses.
|
package/src/shared/sync.ts
CHANGED
|
@@ -25,7 +25,7 @@ export async function ensureRepositories(manifest: OctoManifest, rootDir: string
|
|
|
25
25
|
|
|
26
26
|
if (pending.length === 0) return 0;
|
|
27
27
|
|
|
28
|
-
logger.info(`${pending.length} repository(ies) to clone
|
|
28
|
+
logger.info(`${pending.length} repository(ies) to clone.\n`);
|
|
29
29
|
|
|
30
30
|
// Acquire token once for all clones
|
|
31
31
|
const token = await acquireGitToken();
|