Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 43 additions & 42 deletions .github/workflows/pr-description.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,49 @@ jobs:
USE THIS EXACT TEMPLATE FORMAT (fill in the placeholders and check appropriate boxes):
## Description
[2-4 sentence summary of what this PR does and why]
## Related Issue
[Link any related issues, e.g., "Fixes #123" or "Closes #456", or "None" if not applicable]
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Refactoring (no functional changes)
- [ ] Other (please describe):
## Changes Made
[List the main changes as bullet points]
## Testing
- [ ] I have tested these changes locally
- [ ] I have added/updated tests as needed
- [ ] All tests pass (`npm test`)
## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation (if applicable)
- [ ] My changes generate no new warnings
- [ ] I have updated AGENTS.md if I made architectural changes
## Additional Notes
[Any additional context, or "None"]
---
<sub>🤖 Generated by Claude | [current UTC timestamp in format: YYYY-MM-DD HH:MM UTC]</sub>
> [!NOTE]
> ## Description
>
> [2-4 sentence summary of what this PR does and why]
>
> ## Related Issue
>
> [Link any related issues, e.g., "Fixes #123" or "Closes #456", or "None" if not applicable]
>
> ## Type of Change
>
> - [ ] Bug fix (non-breaking change which fixes an issue)
> - [ ] New feature (non-breaking change which adds functionality)
> - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
> - [ ] Documentation update
> - [ ] Refactoring (no functional changes)
> - [ ] Other (please describe):
>
> ## Changes Made
>
> [List the main changes as bullet points]
>
> ## Testing
>
> - [ ] I have tested these changes locally
> - [ ] I have added/updated tests as needed
> - [ ] All tests pass (`npm test`)
>
> ## Checklist
>
> - [ ] My code follows the project's style guidelines
> - [ ] I have performed a self-review of my own code
> - [ ] I have commented my code, particularly in hard-to-understand areas
> - [ ] I have made corresponding changes to the documentation (if applicable)
> - [ ] My changes generate no new warnings
> - [ ] I have updated AGENTS.md if I made architectural changes
>
> ## Additional Notes
>
> [Any additional context, or "None"]
>
> ---
> <sub>🤖 Generated by Claude | [current UTC timestamp in format: YYYY-MM-DD HH:MM UTC]</sub>
GUIDELINES FOR FILLING THE TEMPLATE:
- Check [x] the appropriate "Type of Change" based on what the code does
Expand Down
23 changes: 23 additions & 0 deletions src/cli/commands/site/browse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Command } from "commander";
import open from "open";
import type { CLIContext } from "@/cli/types.js";
import { runCommand, getSiteUrl } from "@/cli/utils/index.js";
import type { RunCommandResult } from "@/cli/utils/runCommand.js";

async function browseAction(): Promise<RunCommandResult> {
const siteUrl = await getSiteUrl();

if (!process.env.CI) {
await open(siteUrl);
}

return { outroMessage: `Site opened at ${siteUrl}` };
}

export function getSiteBrowseCommand(context: CLIContext): Command {
return new Command("browse")
.description("Open the published site in your browser")
.action(async () => {
await runCommand(browseAction, { requireAuth: true }, context);
});
}
16 changes: 6 additions & 10 deletions src/cli/commands/site/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,10 @@ async function deployAction(options: DeployOptions): Promise<RunCommandResult> {
}

export function getSiteDeployCommand(context: CLIContext): Command {
return new Command("site")
.description("Manage site deployments")
.addCommand(
new Command("deploy")
.description("Deploy built site files to Base44 hosting")
.option("-y, --yes", "Skip confirmation prompt")
.action(async (options: DeployOptions) => {
await runCommand(() => deployAction(options), { requireAuth: true }, context);
})
);
return new Command("deploy")
.description("Deploy built site files to Base44 hosting")
.option("-y, --yes", "Skip confirmation prompt")
.action(async (options: DeployOptions) => {
await runCommand(() => deployAction(options), { requireAuth: true }, context);
});
}
11 changes: 11 additions & 0 deletions src/cli/commands/site/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Command } from "commander";
import type { CLIContext } from "@/cli/types.js";
import { getSiteDeployCommand } from "./deploy.js";
import { getSiteBrowseCommand } from "./browse.js";

export function getSiteCommand(context: CLIContext): Command {
return new Command("site")
.description("Manage site")
.addCommand(getSiteDeployCommand(context))
.addCommand(getSiteBrowseCommand(context));
}
4 changes: 2 additions & 2 deletions src/cli/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { getCreateCommand } from "@/cli/commands/project/create.js";
import { getDashboardCommand } from "@/cli/commands/project/dashboard.js";
import { getDeployCommand } from "@/cli/commands/project/deploy.js";
import { getLinkCommand } from "@/cli/commands/project/link.js";
import { getSiteDeployCommand } from "@/cli/commands/site/deploy.js";
import { getSiteCommand } from "@/cli/commands/site/index.js";
import packageJson from "../../package.json";

export function createProgram(context: CLIContext): Command {
Expand Down Expand Up @@ -48,7 +48,7 @@ export function createProgram(context: CLIContext): Command {
program.addCommand(getFunctionsDeployCommand(context));

// Register site commands
program.addCommand(getSiteDeployCommand(context));
program.addCommand(getSiteCommand(context));

return program;
}
20 changes: 20 additions & 0 deletions src/cli/utils/urls.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { z } from "zod";
import { getBase44ApiUrl } from "@/core/config.js";
import { getAppConfig } from "@/core/project/index.js";
import { base44Client } from "@/core/clients/index.js";

const PublishedUrlResponseSchema = z.object({
url: z.string(),
});

/**
* Gets the dashboard URL for a project.
Expand All @@ -12,3 +18,17 @@ export function getDashboardUrl(projectId?: string): string {
const id = projectId ?? getAppConfig().id;
return `${getBase44ApiUrl()}/apps/${id}/editor/workspace/overview`;
}

/**
* Gets the published site URL for a project by calling the API.
*
* @param projectId - Optional project ID. If not provided, uses cached appId from getAppConfig().
* @returns The published site URL (e.g., https://myapp.base44.app)
* @throws Error if no projectId provided and app config is not initialized, or if app has no slug
*/
export async function getSiteUrl(projectId?: string): Promise<string> {
const id = projectId ?? getAppConfig().id;
const response = await base44Client.get(`api/apps/platform/${id}/published-url`);
const data = PublishedUrlResponseSchema.parse(await response.json());
return data.url;
}
2 changes: 1 addition & 1 deletion src/core/resources/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type { Resource } from "./types.js";
export * from "./entity/index.js";
export * from "./function/index.js";
export * from "./agent/index.js";
export * from "./agent/index.js";
4 changes: 2 additions & 2 deletions tests/cli/dashboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("dashboard command", () => {
it("opens dashboard URL when in a project", async () => {
await t.givenLoggedInWithProject(fixture("basic"));

const result = await t.run("dashboard");
const result = await t.run("dashboard", "browse");

t.expectResult(result).toSucceed();
t.expectResult(result).toContain("Dashboard opened");
Expand All @@ -17,7 +17,7 @@ describe("dashboard command", () => {
it("fails when not in a project directory", async () => {
await t.givenLoggedIn({ email: "test@example.com", name: "Test User" });

const result = await t.run("dashboard");
const result = await t.run("dashboard", "browse");

t.expectResult(result).toFail();
t.expectResult(result).toContain("No Base44 project found");
Expand Down
Loading