@base44-preview/cli 0.0.15-pr.97.98311f6 → 0.0.15-pr.97.a558b80

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/README.md CHANGED
@@ -43,9 +43,31 @@ base44 deploy
43
43
  | Command | Description |
44
44
  |---------|-------------|
45
45
  | `base44 create` | Create a new Base44 project from a template |
46
- | `base44 link` | Link an existing local project to Base44 |
46
+ | `base44 link` | Link a local project to Base44 (create new or link existing) |
47
47
  | `base44 dashboard` | Open the app dashboard in your browser |
48
48
 
49
+ #### Link Command Options
50
+
51
+ The `link` command supports both creating new projects and linking to existing ones:
52
+
53
+ ```bash
54
+ # Interactive mode - choose to create new or link existing
55
+ base44 link
56
+
57
+ # Create a new project (non-interactive)
58
+ base44 link --create --name "my-app" --description "My app description"
59
+
60
+ # Link to an existing project by ID (non-interactive)
61
+ base44 link --existing <app-id>
62
+ ```
63
+
64
+ | Option | Description |
65
+ |--------|-------------|
66
+ | `-c, --create` | Create a new project (skip selection prompt) |
67
+ | `-e, --existing <id>` | Link to an existing project by ID |
68
+ | `-n, --name <name>` | Project name (required with --create) |
69
+ | `-d, --description <desc>` | Project description (optional) |
70
+
49
71
  ### Deployment
50
72
 
51
73
  | Command | Description |
package/dist/cli/index.js CHANGED
@@ -16706,12 +16706,13 @@ const ProjectConfigSchema = object({
16706
16706
  });
16707
16707
  const AppConfigSchema = object({ id: string().min(1, "id cannot be empty") });
16708
16708
  const CreateProjectResponseSchema = looseObject({ id: string() });
16709
- const AppSchema = looseObject({
16709
+ const ProjectSchema = object({
16710
16710
  id: string(),
16711
16711
  name: string(),
16712
- is_managed_source_code: boolean().optional()
16712
+ userDescription: string().optional(),
16713
+ isManagedSourceCode: boolean().optional()
16713
16714
  });
16714
- const AppsResponseSchema = array(AppSchema);
16715
+ const ProjectsResponseSchema = array(ProjectSchema);
16715
16716
 
16716
16717
  //#endregion
16717
16718
  //#region src/core/project/config.ts
@@ -16796,12 +16797,9 @@ async function createProject(projectName, description) {
16796
16797
  } });
16797
16798
  return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
16798
16799
  }
16799
- async function fetchApps() {
16800
- const response = await base44Client.get("api/apps");
16801
- return AppsResponseSchema.parse(await response.json());
16802
- }
16803
- async function fetchLinkableApps() {
16804
- return (await fetchApps()).filter((app) => app.is_managed_source_code === false);
16800
+ async function listProjects() {
16801
+ const response = await base44Client.get(`api/apps?sort=-updated_date&fields=id,name,user_description,is_managed_source_code`);
16802
+ return ProjectsResponseSchema.parse(await response.json());
16805
16803
  }
16806
16804
 
16807
16805
  //#endregion
@@ -38756,20 +38754,21 @@ const deployCommand = new Command("deploy").description("Deploy all project reso
38756
38754
  //#endregion
38757
38755
  //#region src/cli/commands/project/link.ts
38758
38756
  function validateNonInteractiveFlags(command) {
38759
- const { create: create$1, existing, name: name$1 } = command.opts();
38757
+ const { create: create$1, name: name$1, existing, projectId } = command.opts();
38760
38758
  if (create$1 && existing) command.error("--create and --existing cannot be used together");
38759
+ if (existing && !projectId) command.error("--projectId is required when using --existing");
38761
38760
  if (create$1 && !name$1) command.error("--name is required when using --create");
38762
38761
  }
38763
- async function promptForLinkAction(linkableApps) {
38762
+ async function promptForLinkAction() {
38764
38763
  const actionOptions = [{
38765
38764
  value: "create",
38766
38765
  label: "Create a new project",
38767
38766
  hint: "Create a new Base44 project and link it"
38768
38767
  }];
38769
- if (linkableApps.length > 0) actionOptions.push({
38768
+ actionOptions.push({
38770
38769
  value: "choose",
38771
38770
  label: "Link an existing project",
38772
- hint: `Choose from ${linkableApps.length} available project${linkableApps.length === 1 ? "" : "s"}`
38771
+ hint: `Choose from one of your available projects previously created by the Base44 CLI`
38773
38772
  });
38774
38773
  const action = await ve({
38775
38774
  message: "How would you like to link this project?",
@@ -38802,78 +38801,67 @@ async function promptForNewProjectDetails() {
38802
38801
  description: result.description ? result.description.trim() : void 0
38803
38802
  };
38804
38803
  }
38805
- async function promptForExistingApp(linkableApps) {
38806
- const selectedApp = await ve({
38804
+ async function promptForExistingProject(linkableProjects) {
38805
+ const selectedProject = await ve({
38807
38806
  message: "Choose a project to link",
38808
- options: linkableApps.map((app) => ({
38809
- value: app,
38810
- label: app.name
38807
+ options: linkableProjects.map((project) => ({
38808
+ value: project,
38809
+ label: project.name
38811
38810
  }))
38812
38811
  });
38813
- if (pD(selectedApp)) {
38812
+ if (pD(selectedProject)) {
38814
38813
  xe("Operation cancelled.");
38815
38814
  process.exit(0);
38816
38815
  }
38817
- return selectedApp;
38816
+ return selectedProject;
38818
38817
  }
38819
38818
  async function link(options) {
38820
38819
  const projectRoot = await findProjectRoot();
38821
38820
  if (!projectRoot) throw new Error("No Base44 project found. Run this command from a project directory with a config.jsonc file.");
38822
38821
  if (await appConfigExists(projectRoot.root)) throw new Error("Project is already linked. An .app.jsonc file with the appId already exists.");
38823
- if (options.existing) {
38824
- await writeAppConfig(projectRoot.root, options.existing);
38825
- setAppConfig({
38826
- id: options.existing,
38827
- projectRoot: projectRoot.root
38822
+ let finalProjectId;
38823
+ const action = options.existing ? "choose" : options.create ? "create" : await promptForLinkAction();
38824
+ if (action === "choose") {
38825
+ const linkableProjects = (await runTask("Fetching projects...", async () => listProjects(), {
38826
+ successMessage: "Projects fetched",
38827
+ errorMessage: "Failed to fetch projects"
38828
+ })).filter((p$1) => p$1.isManagedSourceCode !== true);
38829
+ if (!linkableProjects.length) return { outroMessage: "No projects available for linking" };
38830
+ const { id: projectId } = options.existing ? { id: options.projectId } : await promptForExistingProject(linkableProjects);
38831
+ await runTask("Linking project...", async () => {
38832
+ await writeAppConfig(projectRoot.root, projectId);
38833
+ setAppConfig({
38834
+ id: projectId,
38835
+ projectRoot: projectRoot.root
38836
+ });
38837
+ }, {
38838
+ successMessage: "Project linked successfully",
38839
+ errorMessage: "Failed to link project"
38828
38840
  });
38829
- M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(options.existing))}`);
38830
- return { outroMessage: "Project linked" };
38831
- }
38832
- if (options.create) {
38833
- const { projectId: projectId$1 } = await runTask("Creating project on Base44...", async () => {
38834
- return await createProject(options.name.trim(), options.description?.trim());
38841
+ finalProjectId = projectId;
38842
+ }
38843
+ if (action === "create") {
38844
+ const { name: name$1, description } = options.create ? {
38845
+ name: options.name.trim(),
38846
+ description: options.description?.trim()
38847
+ } : await promptForNewProjectDetails();
38848
+ const { projectId } = await runTask("Creating project on Base44...", async () => {
38849
+ return await createProject(name$1, description);
38835
38850
  }, {
38836
38851
  successMessage: "Project created successfully",
38837
38852
  errorMessage: "Failed to create project"
38838
38853
  });
38839
- await writeAppConfig(projectRoot.root, projectId$1);
38840
- setAppConfig({
38841
- id: projectId$1,
38842
- projectRoot: projectRoot.root
38843
- });
38844
- M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId$1))}`);
38845
- return { outroMessage: "Project linked" };
38846
- }
38847
- const linkableApps = await runTask("Fetching your projects...", async () => fetchLinkableApps(), {
38848
- successMessage: `Found ${theme.colors.base44Orange("projects")} available for linking`,
38849
- errorMessage: "Failed to fetch projects"
38850
- });
38851
- if (await promptForLinkAction(linkableApps) === "choose") {
38852
- const selectedApp = await promptForExistingApp(linkableApps);
38853
- await writeAppConfig(projectRoot.root, selectedApp.id);
38854
+ await writeAppConfig(projectRoot.root, projectId);
38854
38855
  setAppConfig({
38855
- id: selectedApp.id,
38856
+ id: projectId,
38856
38857
  projectRoot: projectRoot.root
38857
38858
  });
38858
- M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(selectedApp.id))}`);
38859
- return { outroMessage: "Project linked" };
38859
+ finalProjectId = projectId;
38860
38860
  }
38861
- const { name: name$1, description } = await promptForNewProjectDetails();
38862
- const { projectId } = await runTask("Creating project on Base44...", async () => {
38863
- return await createProject(name$1, description);
38864
- }, {
38865
- successMessage: "Project created successfully",
38866
- errorMessage: "Failed to create project"
38867
- });
38868
- await writeAppConfig(projectRoot.root, projectId);
38869
- setAppConfig({
38870
- id: projectId,
38871
- projectRoot: projectRoot.root
38872
- });
38873
- M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId))}`);
38861
+ M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(finalProjectId))}`);
38874
38862
  return { outroMessage: "Project linked" };
38875
38863
  }
38876
- const linkCommand = new Command("link").description("Link a local project to a Base44 project").option("-c, --create", "Create a new project (skip selection prompt)").option("-e, --existing <id>", "Link to an existing project by ID (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38864
+ const linkCommand = new Command("link").description("Link a local project to a Base44 project (create new or link existing)").option("-c, --create", "Create a new project (skip selection prompt)").option("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").option("-e, --existing", "Link to an existing project (skip selection prompt)").option("-p, --projectId <id>", "Project ID (required when --existing is used)").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38877
38865
  await runCommand(() => link(options), {
38878
38866
  requireAuth: true,
38879
38867
  requireAppConfig: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/cli",
3
- "version": "0.0.15-pr.97.98311f6",
3
+ "version": "0.0.15-pr.97.a558b80",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
6
  "main": "./dist/cli/index.js",