Skip to content

Commit 80dcd45

Browse files
sshaderConvex, Inc.
authored andcommitted
Update messaging in CLI for initial flow (#35961)
The main change is adding a prompt on first use for whether to start without an account (default) or to create an account. It's gated behind the `CONVEX_TRY_IT_OUT` env var. I also printed a link to the dashboard in one of the first messages in the dev loop (moved around code to make that happen). Also made it so that the anonymous / self-hosted dashboard can accept a hint for the deployment name to select as a query param GitOrigin-RevId: 2382d48deb29ae2c08f3216483f3bdc290ab859b
1 parent 9554a34 commit 80dcd45

File tree

15 files changed

+236
-98
lines changed

15 files changed

+236
-98
lines changed

npm-packages/convex/src/cli/configure.ts

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import {
4141
} from "./lib/utils/utils.js";
4242
import { writeConvexUrlToEnvFile } from "./lib/envvars.js";
4343
import path from "path";
44-
import { projectDashboardUrl } from "./dashboard.js";
44+
import { projectDashboardUrl } from "./lib/dashboard.js";
4545
import { doCodegen, doInitCodegen } from "./lib/codegen.js";
4646
import { handleLocalDeployment } from "./lib/localDeployment/localDeployment.js";
4747
import {
@@ -54,6 +54,7 @@ import {
5454
DeploymentSelection,
5555
ProjectSelection,
5656
deploymentNameFromSelection,
57+
shouldAllowTryItOut,
5758
} from "./lib/deploymentSelection.js";
5859
import { ensureLoggedIn } from "./lib/login.js";
5960
import { handleTryItOutDeployment } from "./lib/localDeployment/tryitout.js";
@@ -260,21 +261,47 @@ export async function _deploymentCredentialsOrConfigure(
260261
cmdOptions,
261262
);
262263
}
263-
const result = await handleTryItOutDeployment(ctx, {
264+
const shouldPromptForLogin =
265+
deploymentSelection.deploymentName !== null
266+
? "no"
267+
: await promptOptions(ctx, {
268+
message:
269+
"Welcome to Convex! Would you like to login to your account?",
270+
choices: [
271+
{
272+
name: "Start without an account (run Convex locally)",
273+
value: "no",
274+
},
275+
{ name: "Login or create an account", value: "yes" },
276+
],
277+
default: "no",
278+
});
279+
if (shouldPromptForLogin === "no") {
280+
const result = await handleTryItOutDeployment(ctx, {
281+
chosenConfiguration,
282+
deploymentName: deploymentSelection.deploymentName,
283+
...cmdOptions.localOptions,
284+
});
285+
return {
286+
adminKey: result.adminKey,
287+
url: result.deploymentUrl,
288+
deploymentFields: {
289+
deploymentName: result.deploymentName,
290+
deploymentType: "tryitout",
291+
projectSlug: null,
292+
teamSlug: null,
293+
},
294+
};
295+
}
296+
return await handleChooseProject(
297+
ctx,
264298
chosenConfiguration,
265-
deploymentName: deploymentSelection.deploymentName,
266-
...cmdOptions.localOptions,
267-
});
268-
return {
269-
adminKey: result.adminKey,
270-
url: result.deploymentUrl,
271-
deploymentFields: {
272-
deploymentName: result.deploymentName,
273-
deploymentType: "tryitout",
274-
projectSlug: null,
275-
teamSlug: null,
299+
{
300+
globallyForceCloud,
301+
partitionId,
276302
},
277-
};
303+
cmdOptions,
304+
);
278305
}
279306
}
280307
}
@@ -296,9 +323,10 @@ async function handleDeploymentWithinProject(
296323
},
297324
) {
298325
const hasAuth = ctx.bigBrainAuth() !== null;
299-
const loginMessage = hasAuth
300-
? undefined
301-
: `Tip: You can try out Convex without creating an account by clearing the ${CONVEX_DEPLOYMENT_ENV_VAR_NAME} environment variable.`;
326+
const loginMessage =
327+
hasAuth && shouldAllowTryItOut()
328+
? undefined
329+
: `Tip: You can try out Convex without creating an account by clearing the ${CONVEX_DEPLOYMENT_ENV_VAR_NAME} environment variable.`;
302330
await ensureLoggedIn(ctx, {
303331
message: loginMessage,
304332
overrideAuthUrl: cmdOptions.overrideAuthUrl,
@@ -753,6 +781,7 @@ export async function updateEnvAndConfigForDeploymentSelection(
753781
});
754782
await finalizeConfiguration(ctx, {
755783
deploymentType: options.deploymentType,
784+
deploymentName: options.deploymentName,
756785
url: options.url,
757786
wroteToGitIgnore,
758787
changedDeploymentEnvVar,

npm-packages/convex/src/cli/convexExport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
deploymentSelectionWithinProjectFromOptions,
77
loadSelectedDeploymentCredentials,
88
} from "./lib/api.js";
9-
import { deploymentDashboardUrlPage } from "./dashboard.js";
9+
import { deploymentDashboardUrlPage } from "./lib/dashboard.js";
1010
import { actionDescription } from "./lib/command.js";
1111
import { exportFromDeployment } from "./lib/convexExport.js";
1212
import { getDeploymentSelection } from "./lib/deploymentSelection.js";

npm-packages/convex/src/cli/convexImport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "./lib/api.js";
88
import { Command } from "@commander-js/extra-typings";
99
import { actionDescription } from "./lib/command.js";
10-
import { deploymentDashboardUrlPage } from "./dashboard.js";
10+
import { deploymentDashboardUrlPage } from "./lib/dashboard.js";
1111
import { importIntoDeployment } from "./lib/convexImport.js";
1212
import { getDeploymentSelection } from "./lib/deploymentSelection.js";
1313

npm-packages/convex/src/cli/dashboard.ts

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,8 @@ import {
1515
import { actionDescription } from "./lib/command.js";
1616
import { getDeploymentSelection } from "./lib/deploymentSelection.js";
1717
import { isTryItOutDeployment } from "./lib/deployment.js";
18-
import { loadDashboardConfig } from "./lib/localDeployment/filePaths.js";
19-
import {
20-
DEFAULT_LOCAL_DASHBOARD_API_PORT,
21-
checkIfDashboardIsRunning,
22-
} from "./lib/localDeployment/dashboard.js";
18+
import { checkIfDashboardIsRunning } from "./lib/localDeployment/dashboard.js";
19+
import { getDashboardUrl } from "./lib/dashboard.js";
2320

2421
export const DASHBOARD_HOST = process.env.CONVEX_PROVISION_HOST
2522
? "http://localhost:6789"
@@ -52,35 +49,23 @@ export const dashboard = new Command("dashboard")
5249
logMessage(ctx, chalk.yellow(msg));
5350
return;
5451
}
52+
const dashboardUrl = getDashboardUrl(ctx, deployment.deploymentFields);
5553
if (isTryItOutDeployment(deployment.deploymentFields.deploymentName)) {
56-
const dashboardConfig = loadDashboardConfig(ctx);
5754
const warningMessage = `You are not currently running the dashboard locally. Make sure \`npx convex dev\` is running and try again.`;
58-
if (dashboardConfig === null) {
55+
if (dashboardUrl === null) {
5956
logWarning(ctx, warningMessage);
6057
return;
6158
}
62-
const isLocalDashboardRunning =
63-
await checkIfDashboardIsRunning(dashboardConfig);
59+
const isLocalDashboardRunning = await checkIfDashboardIsRunning(ctx);
6460
if (!isLocalDashboardRunning) {
6561
logWarning(ctx, warningMessage);
6662
return;
6763
}
68-
69-
const queryString =
70-
dashboardConfig.apiPort !== DEFAULT_LOCAL_DASHBOARD_API_PORT
71-
? `?apiPort=${dashboardConfig.apiPort}`
72-
: "";
73-
const dashboardUrl = `http://127.0.0.1:${dashboardConfig.port}${queryString}`;
7464
await logOrOpenUrl(ctx, dashboardUrl, options.open);
7565
return;
7666
}
7767

78-
const loginUrl = deploymentDashboardUrlPage(
79-
deployment.deploymentFields.deploymentName,
80-
"",
81-
);
82-
83-
await logOrOpenUrl(ctx, loginUrl, options.open);
68+
await logOrOpenUrl(ctx, dashboardUrl ?? DASHBOARD_HOST, options.open);
8469
});
8570

8671
async function logOrOpenUrl(ctx: Context, url: string, shouldOpen: boolean) {
@@ -91,26 +76,3 @@ async function logOrOpenUrl(ctx: Context, url: string, shouldOpen: boolean) {
9176
logOutput(ctx, url);
9277
}
9378
}
94-
95-
export function deploymentDashboardUrlPage(
96-
configuredDeployment: string | null,
97-
page: string,
98-
): string {
99-
return `${DASHBOARD_HOST}/d/${configuredDeployment}${page}`;
100-
}
101-
102-
export function deploymentDashboardUrl(
103-
team: string,
104-
project: string,
105-
deploymentName: string,
106-
) {
107-
return `${projectDashboardUrl(team, project)}/${deploymentName}`;
108-
}
109-
110-
export function projectDashboardUrl(team: string, project: string) {
111-
return `${teamDashboardUrl(team)}/${project}`;
112-
}
113-
114-
export function teamDashboardUrl(team: string) {
115-
return `${DASHBOARD_HOST}/t/${team}`;
116-
}

npm-packages/convex/src/cli/lib/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
entryPointsByEnvironment,
2020
} from "../../bundler/index.js";
2121
import { version } from "../version.js";
22-
import { deploymentDashboardUrlPage } from "../dashboard.js";
22+
import { deploymentDashboardUrlPage } from "./dashboard.js";
2323
import {
2424
formatSize,
2525
functionsDir,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Context } from "../../bundler/context.js";
2+
import { DeploymentType } from "./api.js";
3+
import { dashboardUrl as localDashboardUrl } from "./localDeployment/dashboard.js";
4+
5+
export const DASHBOARD_HOST = process.env.CONVEX_PROVISION_HOST
6+
? "http://localhost:6789"
7+
: "https://dashboard.convex.dev";
8+
9+
export function getDashboardUrl(
10+
ctx: Context,
11+
{
12+
deploymentName,
13+
deploymentType,
14+
}: {
15+
deploymentName: string;
16+
deploymentType: DeploymentType;
17+
},
18+
): string | null {
19+
switch (deploymentType) {
20+
case "tryitout": {
21+
return localDashboardUrl(ctx, deploymentName);
22+
}
23+
case "local":
24+
case "dev":
25+
case "prod":
26+
case "preview":
27+
return deploymentDashboardUrlPage(deploymentName, "");
28+
default: {
29+
const _exhaustiveCheck: never = deploymentType;
30+
return _exhaustiveCheck;
31+
}
32+
}
33+
}
34+
35+
export function deploymentDashboardUrlPage(
36+
configuredDeployment: string | null,
37+
page: string,
38+
): string {
39+
return `${DASHBOARD_HOST}/d/${configuredDeployment}${page}`;
40+
}
41+
42+
export function deploymentDashboardUrl(
43+
team: string,
44+
project: string,
45+
deploymentName: string,
46+
) {
47+
return `${projectDashboardUrl(team, project)}/${deploymentName}`;
48+
}
49+
50+
export function projectDashboardUrl(team: string, project: string) {
51+
return `${teamDashboardUrl(team)}/${project}`;
52+
}
53+
54+
export function teamDashboardUrl(team: string) {
55+
return `${DASHBOARD_HOST}/t/${team}`;
56+
}

npm-packages/convex/src/cli/lib/init.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import chalk from "chalk";
22
import { Context, logFinishedStep, logMessage } from "../../bundler/context.js";
33
import { DeploymentType } from "./api.js";
44
import { writeConvexUrlToEnvFile } from "./envvars.js";
5+
import { getDashboardUrl } from "./dashboard.js";
56

67
export async function finalizeConfiguration(
78
ctx: Context,
89
options: {
910
functionsPath: string;
1011
deploymentType: DeploymentType;
12+
deploymentName: string;
1113
url: string;
1214
wroteToGitIgnore: boolean;
1315
changedDeploymentEnvVar: boolean;
@@ -17,29 +19,57 @@ export async function finalizeConfiguration(
1719
if (envVarWrite !== null) {
1820
logFinishedStep(
1921
ctx,
20-
`Provisioned a ${options.deploymentType} deployment and saved its:\n` +
22+
`${messageForDeploymentType(options.deploymentType, options.url)} and saved its:\n` +
2123
` name as CONVEX_DEPLOYMENT to .env.local\n` +
2224
` URL as ${envVarWrite.envVar} to ${envVarWrite.envFile}`,
2325
);
2426
} else if (options.changedDeploymentEnvVar) {
2527
logFinishedStep(
2628
ctx,
27-
`Provisioned ${options.deploymentType} deployment and saved its name as CONVEX_DEPLOYMENT to .env.local`,
29+
`${messageForDeploymentType(options.deploymentType, options.url)} and saved its name as CONVEX_DEPLOYMENT to .env.local`,
2830
);
2931
}
3032
if (options.wroteToGitIgnore) {
3133
logMessage(ctx, chalk.gray(` Added ".env.local" to .gitignore`));
3234
}
35+
if (options.deploymentType === "tryitout") {
36+
logMessage(
37+
ctx,
38+
`Run \`npx convex login\` at any time to create an account and link this deployment.`,
39+
);
40+
}
3341

3442
const anyChanges =
3543
options.wroteToGitIgnore ||
3644
options.changedDeploymentEnvVar ||
3745
envVarWrite !== null;
3846
if (anyChanges) {
47+
const dashboardUrl = getDashboardUrl(ctx, {
48+
deploymentName: options.deploymentName,
49+
deploymentType: options.deploymentType,
50+
});
3951
logMessage(
4052
ctx,
4153
`\nWrite your Convex functions in ${chalk.bold(options.functionsPath)}\n` +
42-
"Give us feedback at https://convex.dev/community or [email protected]\n",
54+
"Give us feedback at https://convex.dev/community or [email protected]\n" +
55+
`View the Convex dashboard at ${dashboardUrl}\n`,
4356
);
4457
}
4558
}
59+
60+
function messageForDeploymentType(deploymentType: DeploymentType, url: string) {
61+
switch (deploymentType) {
62+
case "tryitout":
63+
return `Started running a deployment locally at ${url}`;
64+
case "local":
65+
return `Started running a deployment locally at ${url}`;
66+
case "dev":
67+
case "prod":
68+
case "preview":
69+
return `Provisioned a ${deploymentType} deployment`;
70+
default: {
71+
const _exhaustiveCheck: never = deploymentType;
72+
return `Provisioned a ${deploymentType as any} deployment`;
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)