@extenshi/cli 0.9.0 → 0.10.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/dist/cli.js +94 -20
- package/dist/cli.js.map +1 -1
- package/dist/login-bff.d.ts +29 -0
- package/dist/login-bff.d.ts.map +1 -0
- package/dist/login-bff.js +78 -0
- package/dist/login-bff.js.map +1 -0
- package/dist/login-flow.d.ts +109 -0
- package/dist/login-flow.d.ts.map +1 -0
- package/dist/login-flow.js +144 -0
- package/dist/login-flow.js.map +1 -0
- package/dist/login-runtime.d.ts +38 -0
- package/dist/login-runtime.d.ts.map +1 -0
- package/dist/login-runtime.js +186 -0
- package/dist/login-runtime.js.map +1 -0
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -23,11 +23,15 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { readFile } from 'node:fs/promises';
|
|
25
25
|
import { createRequire } from 'node:module';
|
|
26
|
+
import os from 'node:os';
|
|
26
27
|
import * as readline from 'node:readline/promises';
|
|
27
28
|
import { program } from 'commander';
|
|
28
29
|
import { checkAutoUpdate } from './auto-update.js';
|
|
29
30
|
import { loadConfig, saveConfig } from './config.js';
|
|
30
31
|
import { runIconPreview } from './icon.js';
|
|
32
|
+
import { makeLoginBff } from './login-bff.js';
|
|
33
|
+
import { runBrowserLogin } from './login-flow.js';
|
|
34
|
+
import { openBrowser, openLoopback, sleep } from './login-runtime.js';
|
|
31
35
|
import { runPublish } from './publish.js';
|
|
32
36
|
import { runReviewRisk } from './review-risk.js';
|
|
33
37
|
import { parseRefs, parseStore, runRisk } from './risk.js';
|
|
@@ -39,12 +43,11 @@ const MISSING_KEY_HELP = "Looks like you don't have an Extenshi API key set up y
|
|
|
39
43
|
'one-time free allowance (10 catalog reads + 3 scans), so you can try things out\n' +
|
|
40
44
|
'before paying for anything.\n' +
|
|
41
45
|
'\n' +
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
' • add EXTENSHI_API_KEY=... to a .env file in this directory';
|
|
46
|
+
' Run: extenshi login\n' +
|
|
47
|
+
'\n' +
|
|
48
|
+
'That opens your browser, where you can sign in or create an account, and connects\n' +
|
|
49
|
+
'this terminal automatically. In CI, set EXTENSHI_API_KEY from your secrets instead\n' +
|
|
50
|
+
'(or add EXTENSHI_API_KEY=... to a .env file in this directory).';
|
|
48
51
|
const _require = createRequire(import.meta.url);
|
|
49
52
|
const pkg = _require('../package.json');
|
|
50
53
|
initTelemetry({ surface: 'cli', version: pkg.version });
|
|
@@ -296,27 +299,98 @@ icon
|
|
|
296
299
|
await runIconPreview(iconPath, opts, pkg.version);
|
|
297
300
|
});
|
|
298
301
|
});
|
|
302
|
+
/**
|
|
303
|
+
* Ask for a key by hand. Kept as the escape hatch for `--paste`, for servers
|
|
304
|
+
* whose BFF predates the browser handshake, and for anyone who would simply
|
|
305
|
+
* rather paste one.
|
|
306
|
+
*/
|
|
307
|
+
async function promptForKey(apiUrl) {
|
|
308
|
+
console.error('Get a key at https://dojo.extenshi.io/api-keys (sign up at https://auth.extenshi.io/signup).');
|
|
309
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
310
|
+
let apiKey;
|
|
311
|
+
try {
|
|
312
|
+
apiKey = (await rl.question('Extenshi API key: ')).trim();
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
rl.close();
|
|
316
|
+
}
|
|
317
|
+
if (!apiKey)
|
|
318
|
+
throw new Error('no API key provided.');
|
|
319
|
+
const savedPath = saveConfig({ apiKey, apiUrl });
|
|
320
|
+
console.error(`✓ API key saved to ${savedPath}`);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Browser login: open extenshi.io, sign in or sign up there, and let this
|
|
324
|
+
* process pick the key up. See `login-flow.ts` for the handshake.
|
|
325
|
+
*/
|
|
326
|
+
async function loginViaBrowser(apiUrl) {
|
|
327
|
+
const { bffUrl } = await loadConfig(apiUrl);
|
|
328
|
+
const bff = makeLoginBff(bffUrl);
|
|
329
|
+
const outcome = await runBrowserLogin({
|
|
330
|
+
startAuth: (input) => bff.startAuth(input),
|
|
331
|
+
pollAuth: (deviceCode) => bff.pollAuth(deviceCode),
|
|
332
|
+
openLoopback,
|
|
333
|
+
openBrowser,
|
|
334
|
+
sleep,
|
|
335
|
+
now: () => Date.now(),
|
|
336
|
+
// stderr throughout: `login` keeps stdout free so it composes in a pipeline.
|
|
337
|
+
log: (message) => console.error(message),
|
|
338
|
+
}, {
|
|
339
|
+
tool: 'extenshi-cli',
|
|
340
|
+
version: pkg.version,
|
|
341
|
+
platform: process.platform,
|
|
342
|
+
hostname: os.hostname(),
|
|
343
|
+
});
|
|
344
|
+
switch (outcome.kind) {
|
|
345
|
+
case 'success': {
|
|
346
|
+
const savedPath = saveConfig({ apiKey: outcome.apiKey, apiUrl });
|
|
347
|
+
console.error(`\n✓ Connected${outcome.email ? ` as ${outcome.email}` : ''}. Key saved to ${savedPath}.`);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
case 'denied':
|
|
351
|
+
throw new Error('login declined in the browser — nothing was connected.');
|
|
352
|
+
case 'expired':
|
|
353
|
+
throw new Error('the login timed out before it was approved. Run `extenshi login` again.');
|
|
354
|
+
case 'key_limit':
|
|
355
|
+
throw new Error('your account already has the maximum number of API keys. ' +
|
|
356
|
+
'Revoke one at https://dojo.extenshi.io/api-keys, then run `extenshi login` again.');
|
|
357
|
+
case 'unsupported':
|
|
358
|
+
// Older BFF: no handshake to speak. Ask for a key rather than fail.
|
|
359
|
+
console.error('Browser login is not available on this server yet — using a key instead.\n');
|
|
360
|
+
await promptForKey(apiUrl);
|
|
361
|
+
return;
|
|
362
|
+
default:
|
|
363
|
+
throw new Error(`${outcome.message} (you can use \`extenshi login --paste\` instead)`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
299
366
|
program
|
|
300
367
|
.command('login')
|
|
301
|
-
.
|
|
302
|
-
.
|
|
368
|
+
.summary('sign in through your browser and connect this terminal')
|
|
369
|
+
.description('Opens extenshi.io in your browser to sign in (or create a free account), then connects this ' +
|
|
370
|
+
'terminal automatically. The key is stored in ~/.extenshi/config.json, shared with @extenshi/guard.')
|
|
371
|
+
.option('--api-key <key>', 'API key (skips the browser entirely)')
|
|
372
|
+
.option('--paste', 'skip the browser and paste an API key instead')
|
|
303
373
|
.option('--api-url <url>', 'Override the scan API base URL')
|
|
304
374
|
.action(async (opts) => {
|
|
305
375
|
await runCommand('login', async () => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
376
|
+
// An explicitly supplied key is the caller telling us not to open anything.
|
|
377
|
+
const provided = opts.apiKey?.trim();
|
|
378
|
+
if (provided) {
|
|
379
|
+
const savedPath = saveConfig({ apiKey: provided, apiUrl: opts.apiUrl });
|
|
380
|
+
console.error(`✓ API key saved to ${savedPath}`);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (opts.paste) {
|
|
384
|
+
await promptForKey(opts.apiUrl);
|
|
385
|
+
return;
|
|
314
386
|
}
|
|
315
|
-
|
|
316
|
-
|
|
387
|
+
// Nobody is watching a non-interactive session, so waiting on a browser
|
|
388
|
+
// approval there would just hang until the login expired.
|
|
389
|
+
if (!process.stdin.isTTY) {
|
|
390
|
+
throw new Error('browser login needs an interactive terminal. In CI, set EXTENSHI_API_KEY from your ' +
|
|
391
|
+
'secrets instead (create a key at https://dojo.extenshi.io/api-keys).');
|
|
317
392
|
}
|
|
318
|
-
|
|
319
|
-
console.error(`✓ API key saved to ${savedPath}`);
|
|
393
|
+
await loginViaBrowser(opts.apiUrl);
|
|
320
394
|
});
|
|
321
395
|
});
|
|
322
396
|
program.parse();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EACN,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,GACb,MAAM,gBAAgB,CAAA;AAEvB,MAAM,gBAAgB,GACrB,8EAA8E;IAC9E,IAAI;IACJ,8EAA8E;IAC9E,mFAAmF;IACnF,+BAA+B;IAC/B,IAAI;IACJ,+DAA+D;IAC/D,sDAAsD;IACtD,iDAAiD;IACjD,4BAA4B;IAC5B,sDAAsD;IACtD,gEAAgE,CAAA;AAEjE,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,iBAAiB,CAAwB,CAAA;AAE9D,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;AAEvD;;;;;;GAMG;AACH,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,MAA2B;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,YAAY,CAAC,qBAAqB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;IACxE,IAAI,CAAC;QACJ,MAAM,MAAM,EAAE,CAAA;QACd,YAAY,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC,CAAA;QACvF,MAAM,cAAc,EAAE,CAAA;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,YAAY,CAAC,oBAAoB,EAAE;YAClC,OAAO;YACP,UAAU,EAAE,aAAa,CAAC,GAAG,CAAC;YAC9B,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;SACnC,CAAC,CAAA;QACF,YAAY,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;QAC9B,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC5D,sEAAsE;QACtE,6DAA6D;QAC7D,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,GAAG,EAAE,CAAC,CAAA;QACzD,MAAM,cAAc,EAAE,CAAA;QACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;AACF,CAAC;AAED,OAAO;KACL,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEtB,OAAO;KACL,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CACN,6BAA6B,EAC7B,2LAA2L,CAC3L;KACA,MAAM,CACN,iBAAiB,EACjB,uHAAuH,CACvH;KACA,MAAM,CAAC,WAAW,EAAE,gEAAgE,CAAC;KACrF,MAAM,CAAC,QAAQ,EAAE,iDAAiD,CAAC;KACnE,MAAM,CACN,qBAAqB,EACrB,yIAAyI,CACzI;KACA,MAAM,CAAC,kBAAkB,EAAE,yDAAyD,CAAC;KACrF,MAAM,CAAC,aAAa,EAAE,wEAAwE,CAAC;KAC/F,MAAM,CAAC,iBAAiB,EAAE,oEAAoE,CAAC;KAC/F,MAAM,CACN,iBAAiB,EACjB,oHAAoH,CACpH;KACA,MAAM,CACN,2BAA2B,EAC3B,6EAA6E,CAC7E;KACA,MAAM,CACN,6BAA6B,EAC7B,gIAAgI,CAChI;KACA,MAAM,CACN,KAAK,EACJ,QAAgB,EAChB,IAYC,EACA,EAAE;IACH,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAE5C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA;QAClC,CAAC;QAED,oDAAoD;QACpD,MAAM,eAAe,EAAE,CAAA;QAEvB,IAAI,YAAuC,CAAA;QAC3C,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;YAClD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;YAC3D,CAAC;YACD,YAAY,GAAG,GAAG,CAAA;QACnB,CAAC;QAED,gEAAgE;QAChE,4DAA4D;QAC5D,IAAI,MAAkC,CAAA;QACtC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;YAC1C,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACpD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;YAChE,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,yBAAyB,CAAC,CAAA;YAC9E,CAAC;YACD,MAAM,GAAG,CAAC,CAAA;QACX,CAAC;aAAM,CAAC;YACP,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;QACrC,CAAC;QAED,oEAAoE;QACpE,uEAAuE;QACvE,kEAAkE;QAClE,MAAM,UAAU,GAAG,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;QAE9E,MAAM,OAAO,CAAC;YACb,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM;YACN,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,UAAU;YACV,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,KAAK;YAC1C,mEAAmE;YACnE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;YAC3B,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,YAAY;YACZ,UAAU,EAAE,GAAG,CAAC,OAAO;YACvB,iFAAiF;YACjF,uBAAuB,EAAE,IAAI,CAAC,uBAAuB,IAAI,KAAK;YAC9D,MAAM,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC,CACD,CAAA;AAEF,OAAO;KACL,OAAO,CAAC,oBAAoB,CAAC;KAC7B,WAAW,CACX,kFAAkF;IACjF,2FAA2F;IAC3F,4FAA4F;IAC5F,iDAAiD,CAClD;KACA,MAAM,CACN,iBAAiB,EACjB,8FAA8F,CAC9F;KACA,MAAM,CAAC,2BAA2B,EAAE,wDAAwD,CAAC;KAC7F,MAAM,CAAC,wBAAwB,EAAE,iDAAiD,CAAC;KACnF,MAAM,CAAC,YAAY,EAAE,kDAAkD,CAAC;KACxE,MAAM,CAAC,WAAW,EAAE,8EAA8E,CAAC;KACnG,MAAM,CACN,qBAAqB,EACrB,iFAAiF,CACjF;KACA,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC;KAC1C,MAAM,CACN,KAAK,EACJ,QAAgB,EAChB,IAQC,EACA,EAAE;IACH,MAAM,UAAU,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QACtC,qEAAqE;QACrE,wDAAwD;QACxD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;QACjC,MAAM,eAAe,EAAE,CAAA;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;YACzB,EAAE,KAAK,CAAC,GAAG,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;aAClC,MAAM,CAAC,OAAO,CAAC,CAAA;QACjB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;QACpD,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAA;QAC9E,CAAC;QAED,IAAI,WAA+B,CAAA;QACnC,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACpC,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;YACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;YAC/D,CAAC;QACF,CAAC;QAED,MAAM,UAAU,CAAC;YAChB,YAAY,EAAE,QAAQ;YACtB,MAAM,EAAE,MAAuD;YAC/D,mBAAmB,EAAE,IAAI,CAAC,eAAe;YACzC,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;YACpC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;YAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,WAAW;SACX,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC,CACD,CAAA;AAEF,OAAO;KACL,OAAO,CAAC,wBAAwB,CAAC;KACjC,WAAW,CACX,qFAAqF;IACpF,gFAAgF;IAChF,4FAA4F,CAC7F;KACA,MAAM,CACN,qBAAqB,EACrB,gHAAgH,CAChH;KACA,MAAM,CAAC,qBAAqB,EAAE,sEAAsE,CAAC;KACrG,MAAM,CACN,iBAAiB,EACjB,kHAAkH,CAClH;KACA,MAAM,CAAC,QAAQ,EAAE,0BAA0B,CAAC;KAC5C,MAAM,CACN,KAAK,EACJ,QAAgB,EAChB,IAKC,EACA,EAAE;IACH,MAAM,UAAU,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;QAC1C,yEAAyE;QACzE,6DAA6D;QAC7D,MAAM,QAAQ,GAAkD;YAC/D,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,SAAS;YAClB,IAAI,EAAE,MAAM;SACZ,CAAA;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QACjE,CAAC;QAED,uEAAuE;QACvE,qEAAqE;QACrE,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;QACjC,MAAM,eAAe,EAAE,CAAA;QAEvB,MAAM,aAAa,CAAC;YACnB,YAAY,EAAE,QAAQ;YACtB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,yBAAyB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YACzE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,SAAS;YAClC,KAAK;YACL,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;SAC9B,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC,CACD,CAAA;AAEF,OAAO;KACL,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CACX,8FAA8F;IAC7F,4FAA4F;IAC5F,8FAA8F;IAC9F,sCAAsC,CACvC;KACA,MAAM,CACN,iBAAiB,EACjB,uHAAuH,CACvH;KACA,MAAM,CACN,eAAe,EACf,iJAAiJ,CACjJ;KACA,MAAM,CAAC,qBAAqB,EAAE,sEAAsE,CAAC;KACrG,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC;KACnC,MAAM,CACN,KAAK,EACJ,QAA8B,EAC9B,IAA4E,EAC3E,EAAE;IACH,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAA;QACvD,IAAI,CAAC,YAAY,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QACjE,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAA;QACrC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,QAAgB,CAAA;YACpB,IAAI,CAAC;gBACJ,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;YACxD,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;QACzC,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;QAC1D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,CAAC,MAAM,0BAA0B,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACnG,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;QACjC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA;QAClC,CAAC;QACD,MAAM,eAAe,EAAE,CAAA;QAEvB,MAAM,OAAO,CAAC;YACb,IAAI;YACJ,MAAM,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,IAAI,yBAAyB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1F,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;SAC9B,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACH,CAAC,CACD,CAAA;AAEF,MAAM,IAAI,GAAG,OAAO;KAClB,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,6DAA6D,CAAC,CAAA;AAE5E,IAAI;KACF,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CACX,mFAAmF;IAClF,iFAAiF;IACjF,yFAAyF,CAC1F;KACA,MAAM,CACN,eAAe,EACf,mFAAmF,CACnF;KACA,MAAM,CACN,iBAAiB,EACjB,kGAAkG,CAClG;KACA,MAAM,CAAC,WAAW,EAAE,4DAA4D,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,IAAwD,EAAE,EAAE;IAC5F,MAAM,UAAU,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEH,OAAO;KACL,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,iBAAiB,EAAE,wCAAwC,CAAC;KACnE,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,IAA0C,EAAE,EAAE;IAC5D,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QACpC,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAA;QAEhC,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;gBACnC,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,OAAO,CAAC,MAAM;aACtB,CAAC,CAAA;YACF,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YACzD,EAAE,CAAC,KAAK,EAAE,CAAA;QACX,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAA;QACxC,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7D,OAAO,CAAC,KAAK,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEH,OAAO,CAAC,KAAK,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two BFF calls the browser login needs, over plain `fetch`.
|
|
3
|
+
*
|
|
4
|
+
* @extenshi/guard talks to the same endpoints through `@trpc/client`; this
|
|
5
|
+
* package deliberately doesn't carry that dependency (it reaches the BFF with
|
|
6
|
+
* `fetch` everywhere else — see `publish-access.ts`), and adding a client
|
|
7
|
+
* library to a published CLI for two calls would be a poor trade for anyone
|
|
8
|
+
* running it through `npx`.
|
|
9
|
+
*
|
|
10
|
+
* Wire format: tRPC v11, un-batched, no data transformer. A mutation is
|
|
11
|
+
* `POST /api/trpc/<path>` with the input as the raw JSON body, answering
|
|
12
|
+
* `{"result":{"data":…}}` or `{"error":{…}}`.
|
|
13
|
+
*
|
|
14
|
+
* Neither call sends an Authorization header — the caller has no key yet, which
|
|
15
|
+
* is the entire point of the handshake.
|
|
16
|
+
*/
|
|
17
|
+
import type { LoginPollResponse, LoginStartResponse } from './login-flow.js';
|
|
18
|
+
export interface LoginBff {
|
|
19
|
+
startAuth(input: {
|
|
20
|
+
tool: string;
|
|
21
|
+
version: string;
|
|
22
|
+
platform: string;
|
|
23
|
+
hostname?: string;
|
|
24
|
+
redirectUri?: string;
|
|
25
|
+
}): Promise<LoginStartResponse>;
|
|
26
|
+
pollAuth(deviceCode: string): Promise<LoginPollResponse>;
|
|
27
|
+
}
|
|
28
|
+
export declare function makeLoginBff(bffUrl: string): LoginBff;
|
|
29
|
+
//# sourceMappingURL=login-bff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-bff.d.ts","sourceRoot":"","sources":["../src/login-bff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAkE5E,MAAM,WAAW,QAAQ;IACxB,SAAS,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAA;KACpB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;CACxD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAMrD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two BFF calls the browser login needs, over plain `fetch`.
|
|
3
|
+
*
|
|
4
|
+
* @extenshi/guard talks to the same endpoints through `@trpc/client`; this
|
|
5
|
+
* package deliberately doesn't carry that dependency (it reaches the BFF with
|
|
6
|
+
* `fetch` everywhere else — see `publish-access.ts`), and adding a client
|
|
7
|
+
* library to a published CLI for two calls would be a poor trade for anyone
|
|
8
|
+
* running it through `npx`.
|
|
9
|
+
*
|
|
10
|
+
* Wire format: tRPC v11, un-batched, no data transformer. A mutation is
|
|
11
|
+
* `POST /api/trpc/<path>` with the input as the raw JSON body, answering
|
|
12
|
+
* `{"result":{"data":…}}` or `{"error":{…}}`.
|
|
13
|
+
*
|
|
14
|
+
* Neither call sends an Authorization header — the caller has no key yet, which
|
|
15
|
+
* is the entire point of the handshake.
|
|
16
|
+
*/
|
|
17
|
+
/** Long enough for a cold BFF, short enough not to stall the poll cadence. */
|
|
18
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
19
|
+
/**
|
|
20
|
+
* A tRPC error surfaced with the shape `isUnsupportedByServer` reads.
|
|
21
|
+
*
|
|
22
|
+
* The `data.code` matters: `NOT_FOUND` is how a BFF that predates this router
|
|
23
|
+
* answers, and the CLI turns that into "paste a key instead" rather than an
|
|
24
|
+
* error the user can do nothing about.
|
|
25
|
+
*/
|
|
26
|
+
class TrpcHttpError extends Error {
|
|
27
|
+
data;
|
|
28
|
+
constructor(message, data) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.data = data;
|
|
31
|
+
this.name = 'TrpcHttpError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function trpcMutation(bffUrl, path, input) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
37
|
+
try {
|
|
38
|
+
const res = await fetch(`${bffUrl}/api/trpc/${path}`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: { 'Content-Type': 'application/json' },
|
|
41
|
+
body: JSON.stringify(input),
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
});
|
|
44
|
+
// Parse before checking `res.ok`: tRPC returns its error envelope WITH a
|
|
45
|
+
// non-2xx status, and that envelope carries the code the caller branches on.
|
|
46
|
+
const body = (await res.json().catch(() => null));
|
|
47
|
+
if (body?.error) {
|
|
48
|
+
throw new TrpcHttpError(body.error.message ?? `Request failed (${res.status})`, {
|
|
49
|
+
code: body.error.data?.code,
|
|
50
|
+
httpStatus: body.error.data?.httpStatus ?? res.status,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
// A non-tRPC failure (proxy error page, 502 from the load balancer).
|
|
55
|
+
// A bare 404 here means the same thing as tRPC's NOT_FOUND: this
|
|
56
|
+
// deployment doesn't have the router.
|
|
57
|
+
throw new TrpcHttpError(`Request failed (${res.status})`, {
|
|
58
|
+
code: res.status === 404 ? 'NOT_FOUND' : undefined,
|
|
59
|
+
httpStatus: res.status,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (!body?.result || body.result.data === undefined) {
|
|
63
|
+
throw new TrpcHttpError('Malformed response from the server', { httpStatus: res.status });
|
|
64
|
+
}
|
|
65
|
+
return body.result.data;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function makeLoginBff(bffUrl) {
|
|
72
|
+
const base = bffUrl.replace(/\/$/, '');
|
|
73
|
+
return {
|
|
74
|
+
startAuth: (input) => trpcMutation(base, 'cliAuth.start', input),
|
|
75
|
+
pollAuth: (deviceCode) => trpcMutation(base, 'cliAuth.poll', { deviceCode }),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=login-bff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-bff.js","sourceRoot":"","sources":["../src/login-bff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,8EAA8E;AAC9E,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEjC;;;;;;GAMG;AACH,MAAM,aAAc,SAAQ,KAAK;IAGtB;IAFV,YACC,OAAe,EACN,IAA4C;QAErD,KAAK,CAAC,OAAO,CAAC,CAAA;QAFL,SAAI,GAAJ,IAAI,CAAwC;QAGrD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC5B,CAAC;CACD;AAOD,KAAK,UAAU,YAAY,CAAI,MAAc,EAAE,IAAY,EAAE,KAAc;IAC1E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,kBAAkB,CAAC,CAAA;IACtE,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,aAAa,IAAI,EAAE,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC3B,MAAM,EAAE,UAAU,CAAC,MAAM;SACzB,CAAC,CAAA;QAEF,yEAAyE;QACzE,6EAA6E;QAC7E,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAA2B,CAAA;QAE3E,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,mBAAmB,GAAG,CAAC,MAAM,GAAG,EAAE;gBAC/E,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI;gBAC3B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,IAAI,GAAG,CAAC,MAAM;aACrD,CAAC,CAAA;QACH,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACb,qEAAqE;YACrE,iEAAiE;YACjE,sCAAsC;YACtC,MAAM,IAAI,aAAa,CAAC,mBAAmB,GAAG,CAAC,MAAM,GAAG,EAAE;gBACzD,IAAI,EAAE,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;gBAClD,UAAU,EAAE,GAAG,CAAC,MAAM;aACtB,CAAC,CAAA;QACH,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACrD,MAAM,IAAI,aAAa,CAAC,oCAAoC,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAC1F,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;IACxB,CAAC;YAAS,CAAC;QACV,YAAY,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;AACF,CAAC;AAaD,MAAM,UAAU,YAAY,CAAC,MAAc;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO;QACN,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAqB,IAAI,EAAE,eAAe,EAAE,KAAK,CAAC;QACpF,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,YAAY,CAAoB,IAAI,EAAE,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC;KAC/F,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser login, terminal side.
|
|
3
|
+
*
|
|
4
|
+
* `login` opens a browser at extenshi.io, the user signs in (or SIGNS UP — a
|
|
5
|
+
* terminal cannot host a signup form, which is the whole reason this exists),
|
|
6
|
+
* approves the pairing code, and the terminal picks the key up on its own.
|
|
7
|
+
*
|
|
8
|
+
* Two things carry the result back, and only one of them is load-bearing:
|
|
9
|
+
*
|
|
10
|
+
* poll — the source of truth. The key is minted server-side during the
|
|
11
|
+
* claiming poll and returned over TLS, exactly once.
|
|
12
|
+
* loopback — a local one-shot listener the browser is redirected to. It
|
|
13
|
+
* carries NO key: it only wakes the poll loop early so the tab can
|
|
14
|
+
* close itself and the terminal reacts instantly instead of on the
|
|
15
|
+
* next tick. Everything still works when it can't bind a port
|
|
16
|
+
* (locked-down machine, SSH session, a port already taken) — that
|
|
17
|
+
* is the designed fallback, not an error path.
|
|
18
|
+
*
|
|
19
|
+
* Everything here takes its I/O as arguments so the whole state machine is
|
|
20
|
+
* testable without a browser, a socket or a server. That is also what lets one
|
|
21
|
+
* copy serve two published packages with different HTTP stacks: @extenshi/guard
|
|
22
|
+
* speaks tRPC, @extenshi/cli speaks plain fetch, and both hand this the same
|
|
23
|
+
* two functions.
|
|
24
|
+
*
|
|
25
|
+
* TWIN FILE — byte-identical to `tools/extenshi-cli/src/login-flow.ts`.
|
|
26
|
+
* Neither package can import the other at runtime (both are published to npm and
|
|
27
|
+
* built with plain `tsc`), and the repo already duplicates `config.ts` between
|
|
28
|
+
* them for the same reason. Drift is what makes duplication dangerous, so the
|
|
29
|
+
* copies are pinned equal by `login-twin-sync.test.ts` — edit one, copy it over,
|
|
30
|
+
* or the test fails.
|
|
31
|
+
*/
|
|
32
|
+
export interface LoginStartResponse {
|
|
33
|
+
deviceCode: string;
|
|
34
|
+
userCode: string;
|
|
35
|
+
verificationUrl: string;
|
|
36
|
+
verificationUrlComplete: string;
|
|
37
|
+
expiresInSec: number;
|
|
38
|
+
intervalSec: number;
|
|
39
|
+
loopbackAccepted: boolean;
|
|
40
|
+
}
|
|
41
|
+
export type LoginPollStatus = 'pending' | 'approved' | 'denied' | 'expired' | 'claimed' | 'key_limit';
|
|
42
|
+
export interface LoginPollResponse {
|
|
43
|
+
status: LoginPollStatus;
|
|
44
|
+
apiKey?: string;
|
|
45
|
+
email?: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** A bound local listener waiting for the browser to come back. */
|
|
48
|
+
export interface LoopbackListener {
|
|
49
|
+
/** `http://127.0.0.1:<port>/callback` — handed to the server, never composed elsewhere. */
|
|
50
|
+
redirectUri: string;
|
|
51
|
+
/** Resolves when the browser hits it (or never, if it doesn't). */
|
|
52
|
+
hit: Promise<void>;
|
|
53
|
+
close(): void;
|
|
54
|
+
}
|
|
55
|
+
export interface LoginDeps {
|
|
56
|
+
startAuth(input: {
|
|
57
|
+
tool: string;
|
|
58
|
+
version: string;
|
|
59
|
+
platform: string;
|
|
60
|
+
hostname?: string;
|
|
61
|
+
redirectUri?: string;
|
|
62
|
+
}): Promise<LoginStartResponse>;
|
|
63
|
+
pollAuth(deviceCode: string): Promise<LoginPollResponse>;
|
|
64
|
+
/** Bind a loopback listener, or null when this machine won't allow one. */
|
|
65
|
+
openLoopback(): Promise<LoopbackListener | null>;
|
|
66
|
+
/** Launch the user's browser. Returns false when there's nothing to launch. */
|
|
67
|
+
openBrowser(url: string): Promise<boolean>;
|
|
68
|
+
/** Resolve after `ms`, or as soon as `wakeup` settles — whichever is first. */
|
|
69
|
+
sleep(ms: number, wakeup?: Promise<unknown>): Promise<void>;
|
|
70
|
+
now(): number;
|
|
71
|
+
/** Progress lines. Everything user-facing goes to stderr so `--json` stays clean. */
|
|
72
|
+
log(message: string): void;
|
|
73
|
+
}
|
|
74
|
+
export type LoginOutcome = {
|
|
75
|
+
kind: 'success';
|
|
76
|
+
apiKey: string;
|
|
77
|
+
email: string | null;
|
|
78
|
+
} | {
|
|
79
|
+
kind: 'denied';
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'expired';
|
|
82
|
+
} | {
|
|
83
|
+
kind: 'key_limit';
|
|
84
|
+
} | {
|
|
85
|
+
kind: 'unsupported';
|
|
86
|
+
} | {
|
|
87
|
+
kind: 'failed';
|
|
88
|
+
message: string;
|
|
89
|
+
};
|
|
90
|
+
export interface LoginClient {
|
|
91
|
+
tool: string;
|
|
92
|
+
version: string;
|
|
93
|
+
platform: string;
|
|
94
|
+
hostname?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* An older BFF has no `cliAuth` router and answers NOT_FOUND. That is not a
|
|
98
|
+
* failure the user can act on — it means "this deployment predates browser
|
|
99
|
+
* login", and the caller should fall back to asking for a pasted key. Matched on
|
|
100
|
+
* the tRPC error code AND the shape of the 404 body, because the two BFF
|
|
101
|
+
* versions can be live at once during a rollout.
|
|
102
|
+
*/
|
|
103
|
+
export declare function isUnsupportedByServer(err: unknown): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Run the whole login. Returns an outcome rather than throwing, so the CLI
|
|
106
|
+
* decides how each case is worded (and every case has a next step).
|
|
107
|
+
*/
|
|
108
|
+
export declare function runBrowserLogin(deps: LoginDeps, client: LoginClient): Promise<LoginOutcome>;
|
|
109
|
+
//# sourceMappingURL=login-flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-flow.d.ts","sourceRoot":"","sources":["../src/login-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAA;AAErG,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAChC,2FAA2F;IAC3F,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAClB,KAAK,IAAI,IAAI,CAAA;CACb;AAED,MAAM,WAAW,SAAS;IACzB,SAAS,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAA;KACpB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACxD,2EAA2E;IAC3E,YAAY,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAA;IAChD,+EAA+E;IAC/E,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1C,+EAA+E;IAC/E,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,GAAG,IAAI,MAAM,CAAA;IACb,qFAAqF;IACrF,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,MAAM,YAAY,GACrB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtC,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAO3D;AAaD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAuFjG"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser login, terminal side.
|
|
3
|
+
*
|
|
4
|
+
* `login` opens a browser at extenshi.io, the user signs in (or SIGNS UP — a
|
|
5
|
+
* terminal cannot host a signup form, which is the whole reason this exists),
|
|
6
|
+
* approves the pairing code, and the terminal picks the key up on its own.
|
|
7
|
+
*
|
|
8
|
+
* Two things carry the result back, and only one of them is load-bearing:
|
|
9
|
+
*
|
|
10
|
+
* poll — the source of truth. The key is minted server-side during the
|
|
11
|
+
* claiming poll and returned over TLS, exactly once.
|
|
12
|
+
* loopback — a local one-shot listener the browser is redirected to. It
|
|
13
|
+
* carries NO key: it only wakes the poll loop early so the tab can
|
|
14
|
+
* close itself and the terminal reacts instantly instead of on the
|
|
15
|
+
* next tick. Everything still works when it can't bind a port
|
|
16
|
+
* (locked-down machine, SSH session, a port already taken) — that
|
|
17
|
+
* is the designed fallback, not an error path.
|
|
18
|
+
*
|
|
19
|
+
* Everything here takes its I/O as arguments so the whole state machine is
|
|
20
|
+
* testable without a browser, a socket or a server. That is also what lets one
|
|
21
|
+
* copy serve two published packages with different HTTP stacks: @extenshi/guard
|
|
22
|
+
* speaks tRPC, @extenshi/cli speaks plain fetch, and both hand this the same
|
|
23
|
+
* two functions.
|
|
24
|
+
*
|
|
25
|
+
* TWIN FILE — byte-identical to `tools/extenshi-cli/src/login-flow.ts`.
|
|
26
|
+
* Neither package can import the other at runtime (both are published to npm and
|
|
27
|
+
* built with plain `tsc`), and the repo already duplicates `config.ts` between
|
|
28
|
+
* them for the same reason. Drift is what makes duplication dangerous, so the
|
|
29
|
+
* copies are pinned equal by `login-twin-sync.test.ts` — edit one, copy it over,
|
|
30
|
+
* or the test fails.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* An older BFF has no `cliAuth` router and answers NOT_FOUND. That is not a
|
|
34
|
+
* failure the user can act on — it means "this deployment predates browser
|
|
35
|
+
* login", and the caller should fall back to asking for a pasted key. Matched on
|
|
36
|
+
* the tRPC error code AND the shape of the 404 body, because the two BFF
|
|
37
|
+
* versions can be live at once during a rollout.
|
|
38
|
+
*/
|
|
39
|
+
export function isUnsupportedByServer(err) {
|
|
40
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41
|
+
const code = err?.data?.code;
|
|
42
|
+
if (code === 'NOT_FOUND')
|
|
43
|
+
return true;
|
|
44
|
+
return (/No "?mutation"? procedure found|cliAuth|404/i.test(message) && /not found|no procedure/i.test(message));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* How many consecutive poll failures to absorb before giving up.
|
|
48
|
+
*
|
|
49
|
+
* A poll loop that dies on the first dropped packet would strand a user who has
|
|
50
|
+
* ALREADY approved in the browser — the worst moment to fail, because the key
|
|
51
|
+
* exists and only the terminal doesn't know. Wifi handoffs and laptop sleep both
|
|
52
|
+
* produce short bursts of errors, so transient failures are retried and only a
|
|
53
|
+
* sustained outage aborts.
|
|
54
|
+
*/
|
|
55
|
+
const MAX_CONSECUTIVE_POLL_ERRORS = 5;
|
|
56
|
+
/**
|
|
57
|
+
* Run the whole login. Returns an outcome rather than throwing, so the CLI
|
|
58
|
+
* decides how each case is worded (and every case has a next step).
|
|
59
|
+
*/
|
|
60
|
+
export async function runBrowserLogin(deps, client) {
|
|
61
|
+
// Bind the listener BEFORE starting the session: the redirect URI has to be
|
|
62
|
+
// part of the session the server creates, and binding can fail.
|
|
63
|
+
const loopback = await deps.openLoopback();
|
|
64
|
+
try {
|
|
65
|
+
let started;
|
|
66
|
+
try {
|
|
67
|
+
started = await deps.startAuth({
|
|
68
|
+
tool: client.tool,
|
|
69
|
+
version: client.version,
|
|
70
|
+
platform: client.platform,
|
|
71
|
+
hostname: client.hostname,
|
|
72
|
+
redirectUri: loopback?.redirectUri,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
if (isUnsupportedByServer(err))
|
|
77
|
+
return { kind: 'unsupported' };
|
|
78
|
+
return { kind: 'failed', message: err instanceof Error ? err.message : String(err) };
|
|
79
|
+
}
|
|
80
|
+
// The server decides whether it accepted the loopback URL. If it didn't,
|
|
81
|
+
// stop waiting on a callback that will never come.
|
|
82
|
+
const wakeup = loopback && started.loopbackAccepted ? loopback.hit : undefined;
|
|
83
|
+
const opened = await deps.openBrowser(started.verificationUrlComplete);
|
|
84
|
+
deps.log(opened
|
|
85
|
+
? 'Opened your browser to finish signing in.'
|
|
86
|
+
: 'Open this URL in a browser to finish signing in:');
|
|
87
|
+
deps.log(` ${started.verificationUrlComplete}`);
|
|
88
|
+
deps.log('');
|
|
89
|
+
deps.log(` Pairing code: ${started.userCode}`);
|
|
90
|
+
deps.log('');
|
|
91
|
+
deps.log('Check that the code matches, then approve. Waiting… (Ctrl-C to cancel)');
|
|
92
|
+
const deadline = deps.now() + started.expiresInSec * 1000;
|
|
93
|
+
const intervalMs = Math.max(1, started.intervalSec) * 1000;
|
|
94
|
+
let consecutiveErrors = 0;
|
|
95
|
+
while (deps.now() < deadline) {
|
|
96
|
+
let res;
|
|
97
|
+
try {
|
|
98
|
+
res = await deps.pollAuth(started.deviceCode);
|
|
99
|
+
consecutiveErrors = 0;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
if (isUnsupportedByServer(err))
|
|
103
|
+
return { kind: 'unsupported' };
|
|
104
|
+
consecutiveErrors += 1;
|
|
105
|
+
if (consecutiveErrors >= MAX_CONSECUTIVE_POLL_ERRORS) {
|
|
106
|
+
return {
|
|
107
|
+
kind: 'failed',
|
|
108
|
+
message: err instanceof Error ? err.message : String(err),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
await deps.sleep(intervalMs);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
switch (res.status) {
|
|
115
|
+
case 'approved':
|
|
116
|
+
if (!res.apiKey) {
|
|
117
|
+
return { kind: 'failed', message: 'Server approved the login but returned no key.' };
|
|
118
|
+
}
|
|
119
|
+
return { kind: 'success', apiKey: res.apiKey, email: res.email ?? null };
|
|
120
|
+
case 'denied':
|
|
121
|
+
return { kind: 'denied' };
|
|
122
|
+
case 'expired':
|
|
123
|
+
return { kind: 'expired' };
|
|
124
|
+
case 'key_limit':
|
|
125
|
+
return { kind: 'key_limit' };
|
|
126
|
+
case 'claimed':
|
|
127
|
+
// Someone already exchanged this session's code. Not ours to use.
|
|
128
|
+
return {
|
|
129
|
+
kind: 'failed',
|
|
130
|
+
message: 'This login was already completed elsewhere. Run login again.',
|
|
131
|
+
};
|
|
132
|
+
default:
|
|
133
|
+
// Still pending: wait out the interval, but cut it short the moment
|
|
134
|
+
// the browser calls back.
|
|
135
|
+
await deps.sleep(intervalMs, wakeup);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { kind: 'expired' };
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
loopback?.close();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=login-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-flow.js","sourceRoot":"","sources":["../src/login-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real I/O behind `runBrowserLogin`: a one-shot loopback listener, a
|
|
3
|
+
* browser launcher, and an interruptible sleep.
|
|
4
|
+
*
|
|
5
|
+
* Kept apart from `login-flow.ts` so the state machine can be tested without
|
|
6
|
+
* binding sockets or launching applications.
|
|
7
|
+
*
|
|
8
|
+
* TWIN FILE — byte-identical to `tools/extenshi-cli/src/login-runtime.ts`, and
|
|
9
|
+
* pinned equal by `login-twin-sync.test.ts`. See the note in `login-flow.ts`
|
|
10
|
+
* for why the two published packages duplicate rather than share.
|
|
11
|
+
*/
|
|
12
|
+
import type { LoopbackListener } from './login-flow.js';
|
|
13
|
+
/**
|
|
14
|
+
* Bind a loopback listener for the browser to come back to.
|
|
15
|
+
*
|
|
16
|
+
* Returns null — never throws — when binding is not possible: a sandbox that
|
|
17
|
+
* forbids listening, an SSH session with no browser on this machine, an
|
|
18
|
+
* exhausted port range. The login then completes by polling alone, so a null
|
|
19
|
+
* here costs the user a tab they have to close by hand and nothing else.
|
|
20
|
+
*
|
|
21
|
+
* Binds to 127.0.0.1 explicitly rather than all interfaces: it must not become
|
|
22
|
+
* a socket anything off-box can reach, and on macOS binding to 0.0.0.0 is what
|
|
23
|
+
* triggers the "accept incoming connections?" firewall prompt.
|
|
24
|
+
*/
|
|
25
|
+
export declare function openLoopback(): Promise<LoopbackListener | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Launch the browser, reporting whether it plausibly worked.
|
|
28
|
+
*
|
|
29
|
+
* A false return is not an error: SSH sessions, containers and bare servers
|
|
30
|
+
* legitimately have nothing to launch, and the caller prints the URL for the
|
|
31
|
+
* user to open elsewhere. Env vars that mean "no browser here" are honoured
|
|
32
|
+
* before trying, because launching under `CI` would hang a pipeline on a
|
|
33
|
+
* spawned process nobody can see.
|
|
34
|
+
*/
|
|
35
|
+
export declare function openBrowser(url: string): Promise<boolean>;
|
|
36
|
+
/** Sleep, cut short if `wakeup` settles first. */
|
|
37
|
+
export declare function sleep(ms: number, wakeup?: Promise<unknown>): Promise<void>;
|
|
38
|
+
//# sourceMappingURL=login-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-runtime.d.ts","sourceRoot":"","sources":["../src/login-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAsCvD;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAkErE;AAcD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA6B/D;AAED,kDAAkD;AAClD,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB1E"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The real I/O behind `runBrowserLogin`: a one-shot loopback listener, a
|
|
3
|
+
* browser launcher, and an interruptible sleep.
|
|
4
|
+
*
|
|
5
|
+
* Kept apart from `login-flow.ts` so the state machine can be tested without
|
|
6
|
+
* binding sockets or launching applications.
|
|
7
|
+
*
|
|
8
|
+
* TWIN FILE — byte-identical to `tools/extenshi-cli/src/login-runtime.ts`, and
|
|
9
|
+
* pinned equal by `login-twin-sync.test.ts`. See the note in `login-flow.ts`
|
|
10
|
+
* for why the two published packages duplicate rather than share.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from 'node:child_process';
|
|
13
|
+
import http from 'node:http';
|
|
14
|
+
/** Give up on binding rather than hang a login on a firewall prompt. */
|
|
15
|
+
const BIND_TIMEOUT_MS = 2_000;
|
|
16
|
+
const CALLBACK_PATH = '/callback';
|
|
17
|
+
/**
|
|
18
|
+
* The page the browser lands on after approving.
|
|
19
|
+
*
|
|
20
|
+
* Self-contained (no network, no fonts): it is served from a throwaway local
|
|
21
|
+
* server that is about to close, so anything it references would fail to load.
|
|
22
|
+
* `window.close()` only works for script-opened tabs, so the text has to stand
|
|
23
|
+
* on its own when the tab stays put.
|
|
24
|
+
*/
|
|
25
|
+
function resultPage(result) {
|
|
26
|
+
const approved = result !== 'denied';
|
|
27
|
+
const title = approved ? 'Terminal connected' : 'Login declined';
|
|
28
|
+
const body = approved
|
|
29
|
+
? 'You can close this tab and go back to your terminal.'
|
|
30
|
+
: 'Nothing was connected. You can close this tab.';
|
|
31
|
+
return `<!doctype html>
|
|
32
|
+
<html lang="en"><head><meta charset="utf-8"><title>${title} · Extenshi</title>
|
|
33
|
+
<style>
|
|
34
|
+
:root { color-scheme: light dark }
|
|
35
|
+
body { font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; display: grid;
|
|
36
|
+
place-items: center; min-height: 100vh; margin: 0; text-align: center; padding: 24px }
|
|
37
|
+
.card { max-width: 26rem }
|
|
38
|
+
h1 { font-size: 1.25rem; margin: 0 0 .5rem }
|
|
39
|
+
p { margin: 0; opacity: .75 }
|
|
40
|
+
.mark { font-size: 2.5rem; line-height: 1; margin-bottom: .75rem }
|
|
41
|
+
</style></head>
|
|
42
|
+
<body><div class="card">
|
|
43
|
+
<div class="mark">${approved ? '✓' : '✕'}</div>
|
|
44
|
+
<h1>${title}</h1><p>${body}</p>
|
|
45
|
+
</div><script>setTimeout(function(){window.close()},1200)</script></body></html>`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Bind a loopback listener for the browser to come back to.
|
|
49
|
+
*
|
|
50
|
+
* Returns null — never throws — when binding is not possible: a sandbox that
|
|
51
|
+
* forbids listening, an SSH session with no browser on this machine, an
|
|
52
|
+
* exhausted port range. The login then completes by polling alone, so a null
|
|
53
|
+
* here costs the user a tab they have to close by hand and nothing else.
|
|
54
|
+
*
|
|
55
|
+
* Binds to 127.0.0.1 explicitly rather than all interfaces: it must not become
|
|
56
|
+
* a socket anything off-box can reach, and on macOS binding to 0.0.0.0 is what
|
|
57
|
+
* triggers the "accept incoming connections?" firewall prompt.
|
|
58
|
+
*/
|
|
59
|
+
export async function openLoopback() {
|
|
60
|
+
let resolveHit = () => { };
|
|
61
|
+
const hit = new Promise((resolve) => {
|
|
62
|
+
resolveHit = resolve;
|
|
63
|
+
});
|
|
64
|
+
const server = http.createServer((req, res) => {
|
|
65
|
+
const url = new URL(req.url ?? '/', 'http://127.0.0.1');
|
|
66
|
+
if (url.pathname !== CALLBACK_PATH) {
|
|
67
|
+
res.writeHead(404, { 'content-type': 'text/plain' });
|
|
68
|
+
res.end('Not found');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// `result` is display-only: what actually happened is decided by the poll
|
|
72
|
+
// that follows, so a hand-crafted request to this port can change the page
|
|
73
|
+
// wording and nothing else.
|
|
74
|
+
const result = url.searchParams.get('result') ?? 'approved';
|
|
75
|
+
res.writeHead(200, {
|
|
76
|
+
'content-type': 'text/html; charset=utf-8',
|
|
77
|
+
// The page states the outcome of a one-time login; caching it would
|
|
78
|
+
// show a stale verdict on the next one.
|
|
79
|
+
'cache-control': 'no-store',
|
|
80
|
+
});
|
|
81
|
+
res.end(resultPage(result));
|
|
82
|
+
resolveHit();
|
|
83
|
+
});
|
|
84
|
+
const bound = await new Promise((resolve) => {
|
|
85
|
+
const settle = (ok) => {
|
|
86
|
+
clearTimeout(timer);
|
|
87
|
+
server.removeAllListeners('error');
|
|
88
|
+
resolve(ok);
|
|
89
|
+
};
|
|
90
|
+
const timer = setTimeout(() => settle(false), BIND_TIMEOUT_MS);
|
|
91
|
+
server.once('error', () => settle(false));
|
|
92
|
+
try {
|
|
93
|
+
server.listen(0, '127.0.0.1', () => settle(true));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
settle(false);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
if (!bound) {
|
|
100
|
+
server.close();
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const address = server.address();
|
|
104
|
+
if (!address || typeof address.port !== 'number') {
|
|
105
|
+
server.close();
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
// Don't hold the process open: if the browser never comes back, the poll loop
|
|
109
|
+
// (and Ctrl-C) must still be what ends the command.
|
|
110
|
+
server.unref();
|
|
111
|
+
return {
|
|
112
|
+
redirectUri: `http://127.0.0.1:${address.port}${CALLBACK_PATH}`,
|
|
113
|
+
hit,
|
|
114
|
+
close: () => {
|
|
115
|
+
server.close();
|
|
116
|
+
// A tab kept alive by keep-alive would otherwise delay the close.
|
|
117
|
+
server.closeAllConnections?.();
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** Per-platform "open this URL in whatever the user uses". */
|
|
122
|
+
function openCommand(url) {
|
|
123
|
+
if (process.platform === 'darwin')
|
|
124
|
+
return { command: 'open', args: [url] };
|
|
125
|
+
if (process.platform === 'win32') {
|
|
126
|
+
// `start` is a cmd builtin, and its first quoted argument is the WINDOW
|
|
127
|
+
// TITLE — hence the empty "" before the URL, without which a quoted URL
|
|
128
|
+
// silently becomes a title and no browser opens.
|
|
129
|
+
return { command: 'cmd', args: ['/c', 'start', '""', url] };
|
|
130
|
+
}
|
|
131
|
+
return { command: 'xdg-open', args: [url] };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Launch the browser, reporting whether it plausibly worked.
|
|
135
|
+
*
|
|
136
|
+
* A false return is not an error: SSH sessions, containers and bare servers
|
|
137
|
+
* legitimately have nothing to launch, and the caller prints the URL for the
|
|
138
|
+
* user to open elsewhere. Env vars that mean "no browser here" are honoured
|
|
139
|
+
* before trying, because launching under `CI` would hang a pipeline on a
|
|
140
|
+
* spawned process nobody can see.
|
|
141
|
+
*/
|
|
142
|
+
export async function openBrowser(url) {
|
|
143
|
+
if (process.env.EXTENSHI_NO_BROWSER || process.env.CI)
|
|
144
|
+
return false;
|
|
145
|
+
// A Linux box with no display has no browser to open — but WSL does, via the
|
|
146
|
+
// Windows host, so don't treat "no DISPLAY" as decisive there.
|
|
147
|
+
if (process.platform === 'linux' &&
|
|
148
|
+
!process.env.DISPLAY &&
|
|
149
|
+
!process.env.WAYLAND_DISPLAY &&
|
|
150
|
+
!process.env.WSL_DISTRO_NAME) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
const { command, args } = openCommand(url);
|
|
154
|
+
return new Promise((resolve) => {
|
|
155
|
+
try {
|
|
156
|
+
const child = spawn(command, args, { stdio: 'ignore', detached: true });
|
|
157
|
+
// An ENOENT (`xdg-open` not installed) arrives asynchronously, so resolve
|
|
158
|
+
// on whichever comes first: the error, or the process getting far enough
|
|
159
|
+
// to be disowned.
|
|
160
|
+
child.once('error', () => resolve(false));
|
|
161
|
+
child.once('spawn', () => {
|
|
162
|
+
child.unref();
|
|
163
|
+
resolve(true);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
resolve(false);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/** Sleep, cut short if `wakeup` settles first. */
|
|
172
|
+
export function sleep(ms, wakeup) {
|
|
173
|
+
return new Promise((resolve) => {
|
|
174
|
+
const timer = setTimeout(resolve, ms);
|
|
175
|
+
// Never let a pending sleep be the reason the CLI won't exit.
|
|
176
|
+
timer.unref?.();
|
|
177
|
+
void wakeup?.then(() => {
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
resolve();
|
|
180
|
+
}, () => {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
resolve();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=login-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-runtime.js","sourceRoot":"","sources":["../src/login-runtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@extenshi/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Pre-publish security scanner for browser extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"ora": "^8.1.1",
|
|
29
29
|
"posthog-node": "^5.35.1",
|
|
30
30
|
"semver": "^7.6.3",
|
|
31
|
-
"undici": "^7.
|
|
31
|
+
"undici": "^7.29.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^22.16.5",
|
|
35
35
|
"@types/semver": "^7.5.8",
|
|
36
36
|
"typescript": "^5.8.3",
|
|
37
|
-
"vitest": "^3.2.
|
|
37
|
+
"vitest": "^3.2.7"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=20"
|