@nzpr/kb 0.1.4 → 0.1.5
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/lib/init-repo-interactive.js +93 -12
- package/package.json +1 -1
|
@@ -202,6 +202,9 @@ function createReadlinePrompter({ stdin, stdout }) {
|
|
|
202
202
|
askText(label, defaultValue = "", options = {}) {
|
|
203
203
|
return askText(rl, label, defaultValue, options);
|
|
204
204
|
},
|
|
205
|
+
askSecret(label, options = {}) {
|
|
206
|
+
return askSecret({ stdin, stdout, label, ...options });
|
|
207
|
+
},
|
|
205
208
|
askConfirm(label, defaultValue = false) {
|
|
206
209
|
return askConfirm(rl, label, defaultValue);
|
|
207
210
|
},
|
|
@@ -245,6 +248,20 @@ async function askConfirm(rl, label, defaultValue = false) {
|
|
|
245
248
|
}
|
|
246
249
|
}
|
|
247
250
|
|
|
251
|
+
async function askSecret({ stdin, stdout, label, validate = null }) {
|
|
252
|
+
while (true) {
|
|
253
|
+
const value = await readHiddenInput({ stdin, stdout, prompt: `${label}: ` });
|
|
254
|
+
if (!validate) {
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
const error = validate(value);
|
|
258
|
+
if (!error) {
|
|
259
|
+
return value;
|
|
260
|
+
}
|
|
261
|
+
stdout.write(`${error}\n`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
248
265
|
function requireValue(value) {
|
|
249
266
|
return String(value ?? "").trim() ? null : "a value is required";
|
|
250
267
|
}
|
|
@@ -273,20 +290,35 @@ async function ensureInteractiveGitHubAccess({ prompt, stdout, auth }) {
|
|
|
273
290
|
}
|
|
274
291
|
|
|
275
292
|
stdout.write("\nGitHub repo setup needs GitHub authentication.\n");
|
|
276
|
-
stdout.write("
|
|
277
|
-
const loginNow = await prompt.askConfirm("authorize GitHub CLI now", true);
|
|
278
|
-
if (!loginNow) {
|
|
279
|
-
return null;
|
|
280
|
-
}
|
|
293
|
+
stdout.write("You can paste a GitHub token now, use GitHub CLI browser login, or skip repo setup for now.\n");
|
|
281
294
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
while (true) {
|
|
296
|
+
const method = (
|
|
297
|
+
await prompt.askText("authentication method (token/login/skip)", "token", {
|
|
298
|
+
validate: validateAuthMethod
|
|
299
|
+
})
|
|
300
|
+
).toLowerCase();
|
|
301
|
+
if (method === "skip") {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
if (method === "token") {
|
|
305
|
+
const token = await prompt.askSecret("GITHUB_TOKEN", {
|
|
306
|
+
validate: requireValue
|
|
307
|
+
});
|
|
308
|
+
if (token) {
|
|
309
|
+
stdout.write("using the provided GitHub token for repo setup.\n");
|
|
310
|
+
return token;
|
|
311
|
+
}
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
auth.login();
|
|
315
|
+
const token = auth.getToken();
|
|
316
|
+
if (token) {
|
|
317
|
+
stdout.write("GitHub CLI authentication is ready.\n");
|
|
318
|
+
return token;
|
|
319
|
+
}
|
|
320
|
+
stdout.write("GitHub CLI login did not yield a usable token.\n");
|
|
287
321
|
}
|
|
288
|
-
|
|
289
|
-
throw new Error("GitHub authentication did not complete; rerun gh auth login or set GITHUB_TOKEN");
|
|
290
322
|
}
|
|
291
323
|
|
|
292
324
|
const defaultInteractiveGitHubAuth = {
|
|
@@ -306,3 +338,52 @@ const defaultInteractiveGitHubAuth = {
|
|
|
306
338
|
});
|
|
307
339
|
}
|
|
308
340
|
};
|
|
341
|
+
|
|
342
|
+
function validateAuthMethod(value) {
|
|
343
|
+
if (["token", "login", "skip"].includes(String(value ?? "").trim().toLowerCase())) {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
return "enter token, login, or skip";
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function readHiddenInput({ stdin, stdout, prompt }) {
|
|
350
|
+
return new Promise((resolve, reject) => {
|
|
351
|
+
stdout.write(prompt);
|
|
352
|
+
let value = "";
|
|
353
|
+
const wasRaw = Boolean(stdin.isRaw);
|
|
354
|
+
|
|
355
|
+
const cleanup = () => {
|
|
356
|
+
stdin.off("data", onData);
|
|
357
|
+
if (typeof stdin.setRawMode === "function") {
|
|
358
|
+
stdin.setRawMode(wasRaw);
|
|
359
|
+
}
|
|
360
|
+
stdout.write("\n");
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const onData = (chunk) => {
|
|
364
|
+
const text = chunk.toString("utf8");
|
|
365
|
+
for (const char of text) {
|
|
366
|
+
if (char === "\u0003") {
|
|
367
|
+
cleanup();
|
|
368
|
+
reject(new Error("interactive init-repo cancelled"));
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
if (char === "\r" || char === "\n") {
|
|
372
|
+
cleanup();
|
|
373
|
+
resolve(value.trim());
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (char === "\u007f") {
|
|
377
|
+
value = value.slice(0, -1);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
value += char;
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
if (typeof stdin.setRawMode === "function") {
|
|
385
|
+
stdin.setRawMode(true);
|
|
386
|
+
}
|
|
387
|
+
stdin.on("data", onData);
|
|
388
|
+
});
|
|
389
|
+
}
|