mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
db: add login flow for web containers (#10816)
* feat: add login flow for web containers * chore: changeset * chore: remove unused web() * feat: detect github codespaces * fix: add success msg for manual flow * refactor: use URL constructor for login URL Co-authored-by: Matthew Phillips <matthew@skypack.dev> * fix: add .href for url string --------- Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
parent
8d5f3e8656
commit
8e6eb624ae
2 changed files with 53 additions and 25 deletions
5
.changeset/spotty-dots-beg.md
Normal file
5
.changeset/spotty-dots-beg.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"@astrojs/db": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add `astro login` support from online editors like Stackblitz and GitHub Codespaces
|
|
@ -5,11 +5,59 @@ import { listen } from 'async-listen';
|
||||||
import { cyan } from 'kleur/colors';
|
import { cyan } from 'kleur/colors';
|
||||||
import open from 'open';
|
import open from 'open';
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
|
import prompt from 'prompts';
|
||||||
import type { Arguments } from 'yargs-parser';
|
import type { Arguments } from 'yargs-parser';
|
||||||
import { SESSION_LOGIN_FILE } from '../../../tokens.js';
|
import { SESSION_LOGIN_FILE } from '../../../tokens.js';
|
||||||
import type { DBConfig } from '../../../types.js';
|
import type { DBConfig } from '../../../types.js';
|
||||||
import { getAstroStudioUrl } from '../../../utils.js';
|
import { getAstroStudioUrl } from '../../../utils.js';
|
||||||
|
|
||||||
|
const isWebContainer =
|
||||||
|
// Stackblitz heuristic
|
||||||
|
process.versions?.webcontainer ??
|
||||||
|
// Github Codespaces heuristic
|
||||||
|
process.env.CODESPACE_NAME;
|
||||||
|
|
||||||
|
export async function cmd({
|
||||||
|
flags,
|
||||||
|
}: {
|
||||||
|
astroConfig: AstroConfig;
|
||||||
|
dbConfig: DBConfig;
|
||||||
|
flags: Arguments;
|
||||||
|
}) {
|
||||||
|
let session = flags.session;
|
||||||
|
|
||||||
|
if (!session && isWebContainer) {
|
||||||
|
console.log(`Please visit the following URL in your web browser:`);
|
||||||
|
console.log(cyan(`${getAstroStudioUrl()}/auth/cli/login`));
|
||||||
|
console.log(`After login in complete, enter the verification code displayed:`);
|
||||||
|
const response = await prompt({
|
||||||
|
type: 'text',
|
||||||
|
name: 'session',
|
||||||
|
message: 'Verification code:',
|
||||||
|
});
|
||||||
|
if (!response.session) {
|
||||||
|
console.error('Cancelling login.');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
session = response.session;
|
||||||
|
console.log('Successfully logged in');
|
||||||
|
} else if (!session) {
|
||||||
|
const { url, promise } = await createServer();
|
||||||
|
const loginUrl = new URL('/auth/cli/login', getAstroStudioUrl());
|
||||||
|
loginUrl.searchParams.set('returnTo', url);
|
||||||
|
console.log(`Opening the following URL in your browser...`);
|
||||||
|
console.log(cyan(loginUrl.href));
|
||||||
|
console.log(`If something goes wrong, copy-and-paste the URL into your browser.`);
|
||||||
|
open(loginUrl.href);
|
||||||
|
const spinner = ora('Waiting for confirmation...');
|
||||||
|
session = await promise;
|
||||||
|
spinner.succeed('Successfully logged in');
|
||||||
|
}
|
||||||
|
|
||||||
|
await mkdir(new URL('.', SESSION_LOGIN_FILE), { recursive: true });
|
||||||
|
await writeFile(SESSION_LOGIN_FILE, `${session}`);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(fks): How the Astro CLI login process works:
|
// NOTE(fks): How the Astro CLI login process works:
|
||||||
// 1. The Astro CLI creates a temporary server to listen for the session token
|
// 1. The Astro CLI creates a temporary server to listen for the session token
|
||||||
// 2. The user is directed to studio.astro.build/ to login
|
// 2. The user is directed to studio.astro.build/ to login
|
||||||
|
@ -47,28 +95,3 @@ async function createServer(): Promise<{ url: string; promise: Promise<string> }
|
||||||
|
|
||||||
return { url: serverUrl, promise: sessionPromise };
|
return { url: serverUrl, promise: sessionPromise };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cmd({
|
|
||||||
flags,
|
|
||||||
}: {
|
|
||||||
astroConfig: AstroConfig;
|
|
||||||
dbConfig: DBConfig;
|
|
||||||
flags: Arguments;
|
|
||||||
}) {
|
|
||||||
let session = flags.session;
|
|
||||||
|
|
||||||
if (!session) {
|
|
||||||
const { url, promise } = await createServer();
|
|
||||||
const loginUrl = getAstroStudioUrl() + '/auth/cli/login?returnTo=' + encodeURIComponent(url);
|
|
||||||
console.log(`Opening the following URL in your browser...`);
|
|
||||||
console.log(cyan(loginUrl));
|
|
||||||
console.log(`If something goes wrong, copy-and-paste the URL into your browser.`);
|
|
||||||
open(loginUrl);
|
|
||||||
const spinner = ora('Waiting for confirmation...');
|
|
||||||
session = await promise;
|
|
||||||
spinner.succeed('Successfully logged in!');
|
|
||||||
}
|
|
||||||
|
|
||||||
await mkdir(new URL('.', SESSION_LOGIN_FILE), { recursive: true });
|
|
||||||
await writeFile(SESSION_LOGIN_FILE, `${session}`);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue