@base44-preview/cli 0.0.15-pr.99.e192f83 → 0.0.16-pr.107.c96948c

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 --projectId <app-id>
62
+ ```
63
+
64
+ | Option | Description |
65
+ |--------|-------------|
66
+ | `-c, --create` | Create a new project (skip selection prompt) |
67
+ | `-n, --name <name>` | Project name (required with --create) |
68
+ | `-d, --description <desc>` | Project description (optional) |
69
+ | `-p, --projectId <id>` | Link to an existing project by ID (skips selection prompt) |
70
+
49
71
  ### Deployment
50
72
 
51
73
  | Command | Description |
package/dist/cli/index.js CHANGED
@@ -7900,19 +7900,6 @@ var AuthValidationError = class extends Error {
7900
7900
  this.name = "AuthValidationError";
7901
7901
  }
7902
7902
  };
7903
- var ConnectorApiError = class extends Error {
7904
- constructor(message, cause) {
7905
- super(message);
7906
- this.cause = cause;
7907
- this.name = "ConnectorApiError";
7908
- }
7909
- };
7910
- var ConnectorValidationError = class extends Error {
7911
- constructor(message) {
7912
- super(message);
7913
- this.name = "ConnectorValidationError";
7914
- }
7915
- };
7916
7903
 
7917
7904
  //#endregion
7918
7905
  //#region src/core/consts.ts
@@ -16719,6 +16706,13 @@ const ProjectConfigSchema = object({
16719
16706
  });
16720
16707
  const AppConfigSchema = object({ id: string().min(1, "id cannot be empty") });
16721
16708
  const CreateProjectResponseSchema = looseObject({ id: string() });
16709
+ const ProjectSchema = object({
16710
+ id: string(),
16711
+ name: string(),
16712
+ userDescription: string().optional(),
16713
+ isManagedSourceCode: boolean().optional()
16714
+ });
16715
+ const ProjectsResponseSchema = array(ProjectSchema);
16722
16716
 
16723
16717
  //#endregion
16724
16718
  //#region src/core/project/config.ts
@@ -16803,6 +16797,13 @@ async function createProject(projectName, description) {
16803
16797
  } });
16804
16798
  return { projectId: CreateProjectResponseSchema.parse(await response.json()).id };
16805
16799
  }
16800
+ async function listProjects() {
16801
+ const response = await base44Client.get(`api/apps`, { searchParams: {
16802
+ "sort": "-updated_date",
16803
+ "fields": "id,name,user_description,is_managed_source_code"
16804
+ } });
16805
+ return ProjectsResponseSchema.parse(await response.json());
16806
+ }
16806
16807
 
16807
16808
  //#endregion
16808
16809
  //#region node_modules/ejs/lib/utils.js
@@ -31005,10 +31006,7 @@ const theme = {
31005
31006
  base44OrangeBackground: source_default.bgHex("#E86B3C"),
31006
31007
  shinyOrange: source_default.hex("#FFD700"),
31007
31008
  links: source_default.hex("#00D4FF"),
31008
- white: source_default.white,
31009
- success: source_default.green,
31010
- warning: source_default.yellow,
31011
- error: source_default.red
31009
+ white: source_default.white
31012
31010
  },
31013
31011
  styles: {
31014
31012
  header: source_default.dim,
@@ -38759,20 +38757,33 @@ const deployCommand = new Command("deploy").description("Deploy all project reso
38759
38757
  //#endregion
38760
38758
  //#region src/cli/commands/project/link.ts
38761
38759
  function validateNonInteractiveFlags(command) {
38762
- const { create: create$1, name: name$1 } = command.opts();
38760
+ const { create: create$1, name: name$1, projectId } = command.opts();
38761
+ if (create$1 && projectId) command.error("--create and --projectId cannot be used together");
38763
38762
  if (create$1 && !name$1) command.error("--name is required when using --create");
38764
38763
  }
38765
- async function promptForProjectDetails() {
38764
+ async function promptForLinkAction() {
38766
38765
  const actionOptions = [{
38767
38766
  value: "create",
38768
38767
  label: "Create a new project",
38769
38768
  hint: "Create a new Base44 project and link it"
38770
38769
  }];
38770
+ actionOptions.push({
38771
+ value: "choose",
38772
+ label: "Link an existing project",
38773
+ hint: `Choose from one of your available projects previously created by the Base44 CLI`
38774
+ });
38775
+ const action = await ve({
38776
+ message: "How would you like to link this project?",
38777
+ options: actionOptions
38778
+ });
38779
+ if (pD(action)) {
38780
+ xe("Operation cancelled.");
38781
+ process.exit(0);
38782
+ }
38783
+ return action;
38784
+ }
38785
+ async function promptForNewProjectDetails() {
38771
38786
  const result = await Ce({
38772
- action: () => ve({
38773
- message: "How would you like to link this project?",
38774
- options: actionOptions
38775
- }),
38776
38787
  name: () => {
38777
38788
  return he({
38778
38789
  message: "What is the name of your project?",
@@ -38792,29 +38803,71 @@ async function promptForProjectDetails() {
38792
38803
  description: result.description ? result.description.trim() : void 0
38793
38804
  };
38794
38805
  }
38806
+ async function promptForExistingProject(linkableProjects) {
38807
+ const selectedProject = await ve({
38808
+ message: "Choose a project to link",
38809
+ options: linkableProjects.map((project) => ({
38810
+ value: project,
38811
+ label: project.name
38812
+ }))
38813
+ });
38814
+ if (pD(selectedProject)) {
38815
+ xe("Operation cancelled.");
38816
+ process.exit(0);
38817
+ }
38818
+ return selectedProject;
38819
+ }
38795
38820
  async function link(options) {
38796
38821
  const projectRoot = await findProjectRoot();
38797
38822
  if (!projectRoot) throw new Error("No Base44 project found. Run this command from a project directory with a config.jsonc file.");
38798
38823
  if (await appConfigExists(projectRoot.root)) throw new Error("Project is already linked. An .app.jsonc file with the appId already exists.");
38799
- const { name: name$1, description } = options.create ? {
38800
- name: options.name.trim(),
38801
- description: options.description?.trim()
38802
- } : await promptForProjectDetails();
38803
- const { projectId } = await runTask("Creating project on Base44...", async () => {
38804
- return await createProject(name$1, description);
38805
- }, {
38806
- successMessage: "Project created successfully",
38807
- errorMessage: "Failed to create project"
38808
- });
38809
- await writeAppConfig(projectRoot.root, projectId);
38810
- setAppConfig({
38811
- id: projectId,
38812
- projectRoot: projectRoot.root
38813
- });
38814
- M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(projectId))}`);
38824
+ let finalProjectId;
38825
+ const action = options.projectId ? "choose" : options.create ? "create" : await promptForLinkAction();
38826
+ if (action === "choose") {
38827
+ const linkableProjects = (await runTask("Fetching projects...", async () => listProjects(), {
38828
+ successMessage: "Projects fetched",
38829
+ errorMessage: "Failed to fetch projects"
38830
+ })).filter((p$1) => p$1.isManagedSourceCode !== true);
38831
+ if (!linkableProjects.length) return { outroMessage: "No projects available for linking" };
38832
+ let projectId;
38833
+ if (options.projectId) {
38834
+ if (!linkableProjects.find((p$1) => p$1.id === options.projectId)) throw new Error(`Project with ID "${options.projectId}" not found or not available for linking.`);
38835
+ projectId = options.projectId;
38836
+ } else projectId = (await promptForExistingProject(linkableProjects)).id;
38837
+ await runTask("Linking project...", async () => {
38838
+ await writeAppConfig(projectRoot.root, projectId);
38839
+ setAppConfig({
38840
+ id: projectId,
38841
+ projectRoot: projectRoot.root
38842
+ });
38843
+ }, {
38844
+ successMessage: "Project linked successfully",
38845
+ errorMessage: "Failed to link project"
38846
+ });
38847
+ finalProjectId = projectId;
38848
+ }
38849
+ if (action === "create") {
38850
+ const { name: name$1, description } = options.create ? {
38851
+ name: options.name.trim(),
38852
+ description: options.description?.trim()
38853
+ } : await promptForNewProjectDetails();
38854
+ const { projectId } = await runTask("Creating project on Base44...", async () => {
38855
+ return await createProject(name$1, description);
38856
+ }, {
38857
+ successMessage: "Project created successfully",
38858
+ errorMessage: "Failed to create project"
38859
+ });
38860
+ await writeAppConfig(projectRoot.root, projectId);
38861
+ setAppConfig({
38862
+ id: projectId,
38863
+ projectRoot: projectRoot.root
38864
+ });
38865
+ finalProjectId = projectId;
38866
+ }
38867
+ M.message(`${theme.styles.header("Dashboard")}: ${theme.colors.links(getDashboardUrl(finalProjectId))}`);
38815
38868
  return { outroMessage: "Project linked" };
38816
38869
  }
38817
- 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("-n, --name <name>", "Project name (required when --create is used)").option("-d, --description <description>", "Project description").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38870
+ 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("-p, --projectId <id>", "Project ID to link to an existing project (skips selection prompt)").hook("preAction", validateNonInteractiveFlags).action(async (options) => {
38818
38871
  await runCommand(() => link(options), {
38819
38872
  requireAuth: true,
38820
38873
  requireAppConfig: false
@@ -38842,393 +38895,9 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
38842
38895
  await runCommand(() => deployAction(options), { requireAuth: true });
38843
38896
  }));
38844
38897
 
38845
- //#endregion
38846
- //#region src/core/connectors/schema.ts
38847
- /**
38848
- * Response from POST /api/apps/{app_id}/external-auth/initiate
38849
- */
38850
- const InitiateResponseSchema = object({
38851
- redirect_url: string().optional(),
38852
- connection_id: string().optional(),
38853
- already_authorized: boolean().optional(),
38854
- other_user_email: string().optional(),
38855
- error: string().optional()
38856
- });
38857
- /**
38858
- * Response from GET /api/apps/{app_id}/external-auth/status
38859
- */
38860
- const StatusResponseSchema = object({
38861
- status: _enum([
38862
- "ACTIVE",
38863
- "PENDING",
38864
- "FAILED"
38865
- ]),
38866
- account_email: string().optional(),
38867
- error: string().optional()
38868
- });
38869
- /**
38870
- * A connected integration from the list endpoint
38871
- */
38872
- const ConnectorSchema = object({
38873
- integration_type: string(),
38874
- status: string(),
38875
- connected_at: string().optional(),
38876
- account_info: object({
38877
- email: string().optional(),
38878
- name: string().optional()
38879
- }).optional()
38880
- }).transform((data) => ({
38881
- integrationType: data.integration_type,
38882
- status: data.status,
38883
- connectedAt: data.connected_at,
38884
- accountInfo: data.account_info
38885
- }));
38886
- /**
38887
- * Response from GET /api/apps/{app_id}/external-auth/list
38888
- */
38889
- const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
38890
- /**
38891
- * Generic API error response
38892
- */
38893
- const ApiErrorSchema = object({
38894
- error: string(),
38895
- detail: string().optional()
38896
- });
38897
-
38898
- //#endregion
38899
- //#region src/core/connectors/api.ts
38900
- /**
38901
- * Initiates OAuth flow for a connector integration.
38902
- * Returns a redirect URL to open in the browser.
38903
- */
38904
- async function initiateOAuth(integrationType, scopes = null) {
38905
- const response = await getAppClient().post("external-auth/initiate", {
38906
- json: {
38907
- integration_type: integrationType,
38908
- scopes
38909
- },
38910
- throwHttpErrors: false
38911
- });
38912
- const json = await response.json();
38913
- if (!response.ok) {
38914
- const errorResult = ApiErrorSchema.safeParse(json);
38915
- if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
38916
- throw new ConnectorApiError(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
38917
- }
38918
- const result = InitiateResponseSchema.safeParse(json);
38919
- if (!result.success) throw new ConnectorValidationError(`Invalid initiate response from server: ${result.error.message}`);
38920
- return result.data;
38921
- }
38922
- /**
38923
- * Checks the status of an OAuth connection attempt.
38924
- */
38925
- async function checkOAuthStatus(integrationType, connectionId) {
38926
- const response = await getAppClient().get("external-auth/status", {
38927
- searchParams: {
38928
- integration_type: integrationType,
38929
- connection_id: connectionId
38930
- },
38931
- throwHttpErrors: false
38932
- });
38933
- const json = await response.json();
38934
- if (!response.ok) {
38935
- const errorResult = ApiErrorSchema.safeParse(json);
38936
- if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
38937
- throw new ConnectorApiError(`Failed to check OAuth status: ${response.status} ${response.statusText}`);
38938
- }
38939
- const result = StatusResponseSchema.safeParse(json);
38940
- if (!result.success) throw new ConnectorValidationError(`Invalid status response from server: ${result.error.message}`);
38941
- return result.data;
38942
- }
38943
- /**
38944
- * Lists all connected integrations for the current app.
38945
- */
38946
- async function listConnectors() {
38947
- const response = await getAppClient().get("external-auth/list", { throwHttpErrors: false });
38948
- const json = await response.json();
38949
- if (!response.ok) {
38950
- const errorResult = ApiErrorSchema.safeParse(json);
38951
- if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
38952
- throw new ConnectorApiError(`Failed to list connectors: ${response.status} ${response.statusText}`);
38953
- }
38954
- const result = ListResponseSchema.safeParse(json);
38955
- if (!result.success) throw new ConnectorValidationError(`Invalid list response from server: ${result.error.message}`);
38956
- return result.data.integrations;
38957
- }
38958
- /**
38959
- * Disconnects (soft delete) a connector integration.
38960
- */
38961
- async function disconnectConnector(integrationType) {
38962
- const response = await getAppClient().delete(`external-auth/integrations/${integrationType}`, { throwHttpErrors: false });
38963
- if (!response.ok) {
38964
- const json = await response.json();
38965
- const errorResult = ApiErrorSchema.safeParse(json);
38966
- if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
38967
- throw new ConnectorApiError(`Failed to disconnect connector: ${response.status} ${response.statusText}`);
38968
- }
38969
- }
38970
-
38971
- //#endregion
38972
- //#region src/core/connectors/constants.ts
38973
- /**
38974
- * Supported OAuth connector integrations.
38975
- * Based on apper/backend/app/external_auth/models/constants.py
38976
- */
38977
- const SUPPORTED_INTEGRATIONS = [
38978
- "googlecalendar",
38979
- "googledrive",
38980
- "gmail",
38981
- "googlesheets",
38982
- "googledocs",
38983
- "googleslides",
38984
- "slack",
38985
- "notion",
38986
- "salesforce",
38987
- "hubspot",
38988
- "linkedin",
38989
- "tiktok"
38990
- ];
38991
- /**
38992
- * Display names for integrations (for CLI output)
38993
- */
38994
- const INTEGRATION_DISPLAY_NAMES = {
38995
- googlecalendar: "Google Calendar",
38996
- googledrive: "Google Drive",
38997
- gmail: "Gmail",
38998
- googlesheets: "Google Sheets",
38999
- googledocs: "Google Docs",
39000
- googleslides: "Google Slides",
39001
- slack: "Slack",
39002
- notion: "Notion",
39003
- salesforce: "Salesforce",
39004
- hubspot: "HubSpot",
39005
- linkedin: "LinkedIn",
39006
- tiktok: "TikTok"
39007
- };
39008
- function isValidIntegration(type) {
39009
- return SUPPORTED_INTEGRATIONS.includes(type);
39010
- }
39011
- function getIntegrationDisplayName(type) {
39012
- if (isValidIntegration(type)) return INTEGRATION_DISPLAY_NAMES[type];
39013
- return type;
39014
- }
39015
-
39016
- //#endregion
39017
- //#region src/cli/commands/connectors/add.ts
39018
- const POLL_INTERVAL_MS = 2e3;
39019
- const POLL_TIMEOUT_MS = 300 * 1e3;
39020
- async function promptForIntegrationType() {
39021
- const selected = await ve({
39022
- message: "Select an integration to connect:",
39023
- options: SUPPORTED_INTEGRATIONS.map((type) => ({
39024
- value: type,
39025
- label: getIntegrationDisplayName(type)
39026
- }))
39027
- });
39028
- if (pD(selected)) return null;
39029
- return selected;
39030
- }
39031
- async function waitForOAuthCompletion(integrationType, connectionId) {
39032
- let accountEmail;
39033
- let error;
39034
- try {
39035
- await runTask("Waiting for authorization...", async (updateMessage) => {
39036
- await pWaitFor(async () => {
39037
- const status = await checkOAuthStatus(integrationType, connectionId);
39038
- if (status.status === "ACTIVE") {
39039
- accountEmail = status.account_email;
39040
- return true;
39041
- }
39042
- if (status.status === "FAILED") {
39043
- error = status.error || "Authorization failed";
39044
- throw new Error(error);
39045
- }
39046
- updateMessage("Waiting for authorization in browser...");
39047
- return false;
39048
- }, {
39049
- interval: POLL_INTERVAL_MS,
39050
- timeout: POLL_TIMEOUT_MS
39051
- });
39052
- }, {
39053
- successMessage: "Authorization completed!",
39054
- errorMessage: "Authorization failed"
39055
- });
39056
- return {
39057
- success: true,
39058
- accountEmail
39059
- };
39060
- } catch (err) {
39061
- if (err instanceof Error && err.message.includes("timed out")) return {
39062
- success: false,
39063
- error: "Authorization timed out. Please try again."
39064
- };
39065
- return {
39066
- success: false,
39067
- error: error || (err instanceof Error ? err.message : "Unknown error")
39068
- };
39069
- }
39070
- }
39071
- async function addConnector(integrationType) {
39072
- let selectedType;
39073
- if (!integrationType) {
39074
- const prompted = await promptForIntegrationType();
39075
- if (!prompted) return { outroMessage: "Cancelled" };
39076
- selectedType = prompted;
39077
- } else {
39078
- if (!isValidIntegration(integrationType)) {
39079
- const supportedList = SUPPORTED_INTEGRATIONS.join(", ");
39080
- throw new Error(`Unsupported connector: ${integrationType}\nSupported connectors: ${supportedList}`);
39081
- }
39082
- selectedType = integrationType;
39083
- }
39084
- const displayName = getIntegrationDisplayName(selectedType);
39085
- const initiateResponse = await runTask(`Initiating ${displayName} connection...`, async () => {
39086
- return await initiateOAuth(selectedType);
39087
- }, {
39088
- successMessage: `${displayName} OAuth initiated`,
39089
- errorMessage: `Failed to initiate ${displayName} connection`
39090
- });
39091
- if (initiateResponse.already_authorized) return { outroMessage: `Already connected to ${theme.styles.bold(displayName)}` };
39092
- if (initiateResponse.error === "different_user" && initiateResponse.other_user_email) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.other_user_email}`);
39093
- if (!initiateResponse.redirect_url || !initiateResponse.connection_id) throw new Error("Invalid response from server: missing redirect URL or connection ID");
39094
- M.info(`Opening browser for ${displayName} authorization...`);
39095
- await open_default(initiateResponse.redirect_url);
39096
- const result = await waitForOAuthCompletion(selectedType, initiateResponse.connection_id);
39097
- if (!result.success) throw new Error(result.error || "Authorization failed");
39098
- const accountInfo = result.accountEmail ? ` as ${theme.styles.bold(result.accountEmail)}` : "";
39099
- return { outroMessage: `Successfully connected to ${theme.styles.bold(displayName)}${accountInfo}` };
39100
- }
39101
- const connectorsAddCommand = new Command("connectors:add").argument("[type]", "Integration type (e.g., slack, notion, googlecalendar)").description("Connect an OAuth integration").action(async (type) => {
39102
- await runCommand(() => addConnector(type), {
39103
- requireAuth: true,
39104
- requireAppConfig: true
39105
- });
39106
- });
39107
-
39108
- //#endregion
39109
- //#region src/cli/commands/connectors/list.ts
39110
- function formatDate(dateString) {
39111
- if (!dateString) return "-";
39112
- try {
39113
- return new Date(dateString).toLocaleDateString("en-US", {
39114
- year: "numeric",
39115
- month: "short",
39116
- day: "numeric"
39117
- });
39118
- } catch {
39119
- return dateString;
39120
- }
39121
- }
39122
- function formatStatus(status) {
39123
- const normalized = status.toLowerCase();
39124
- if (normalized === "active" || normalized === "connected") return theme.colors.success("● active");
39125
- if (normalized === "expired") return theme.colors.warning("● expired");
39126
- if (normalized === "failed" || normalized === "disconnected") return theme.colors.error("● disconnected");
39127
- return status;
39128
- }
39129
- async function listConnectorsCommand() {
39130
- const connectors = await runTask("Fetching connectors...", async () => {
39131
- return await listConnectors();
39132
- }, {
39133
- successMessage: "Connectors loaded",
39134
- errorMessage: "Failed to fetch connectors"
39135
- });
39136
- if (connectors.length === 0) {
39137
- M.info("No connectors configured for this app.");
39138
- M.info(`Run ${theme.styles.bold("base44 connectors:add")} to connect an integration.`);
39139
- return { outroMessage: "" };
39140
- }
39141
- console.log();
39142
- console.log(theme.styles.bold("Connected Integrations:"));
39143
- console.log();
39144
- const headers = [
39145
- "Type",
39146
- "Account",
39147
- "Status",
39148
- "Connected"
39149
- ];
39150
- const colWidths = [
39151
- 20,
39152
- 30,
39153
- 15,
39154
- 15
39155
- ];
39156
- const headerRow = headers.map((h$2, i$1) => h$2.padEnd(colWidths[i$1])).join(" ");
39157
- console.log(theme.styles.dim(headerRow));
39158
- console.log(theme.styles.dim("─".repeat(headerRow.length)));
39159
- for (const connector of connectors) {
39160
- const type = getIntegrationDisplayName(connector.integrationType).padEnd(colWidths[0]);
39161
- const account = (connector.accountInfo?.email || connector.accountInfo?.name || "-").padEnd(colWidths[1]);
39162
- const status = formatStatus(connector.status);
39163
- const connected = formatDate(connector.connectedAt).padEnd(colWidths[3]);
39164
- console.log(`${type} ${account} ${status.padEnd(colWidths[2] + 10)} ${connected}`);
39165
- }
39166
- console.log();
39167
- return { outroMessage: `${connectors.length} connector${connectors.length === 1 ? "" : "s"} configured` };
39168
- }
39169
- const connectorsListCommand = new Command("connectors:list").description("List all connected OAuth integrations").action(async () => {
39170
- await runCommand(listConnectorsCommand, {
39171
- requireAuth: true,
39172
- requireAppConfig: true
39173
- });
39174
- });
39175
-
39176
- //#endregion
39177
- //#region src/cli/commands/connectors/remove.ts
39178
- async function promptForConnectorToRemove(connectors) {
39179
- const selected = await ve({
39180
- message: "Select a connector to remove:",
39181
- options: connectors.map((c$1) => ({
39182
- value: c$1.integrationType,
39183
- label: `${getIntegrationDisplayName(c$1.integrationType)}${c$1.accountInfo?.email ? ` (${c$1.accountInfo.email})` : ""}`
39184
- }))
39185
- });
39186
- if (pD(selected)) return null;
39187
- return selected;
39188
- }
39189
- async function removeConnectorCommand(integrationType) {
39190
- const connectors = await runTask("Fetching connectors...", async () => {
39191
- return await listConnectors();
39192
- }, {
39193
- successMessage: "Connectors loaded",
39194
- errorMessage: "Failed to fetch connectors"
39195
- });
39196
- if (connectors.length === 0) return { outroMessage: "No connectors to remove" };
39197
- let selectedType;
39198
- if (!integrationType) {
39199
- const prompted = await promptForConnectorToRemove(connectors);
39200
- if (!prompted) return { outroMessage: "Cancelled" };
39201
- selectedType = prompted;
39202
- } else {
39203
- if (!isValidIntegration(integrationType)) throw new Error(`Invalid connector type: ${integrationType}`);
39204
- if (!connectors.some((c$1) => c$1.integrationType === integrationType)) throw new Error(`No ${getIntegrationDisplayName(integrationType)} connector found for this app`);
39205
- selectedType = integrationType;
39206
- }
39207
- const displayName = getIntegrationDisplayName(selectedType);
39208
- const connector = connectors.find((c$1) => c$1.integrationType === selectedType);
39209
- const shouldRemove = await ye({
39210
- message: `Disconnect ${displayName}${connector?.accountInfo?.email ? ` (${connector.accountInfo.email})` : ""}?`,
39211
- initialValue: false
39212
- });
39213
- if (pD(shouldRemove) || !shouldRemove) return { outroMessage: "Cancelled" };
39214
- await runTask(`Disconnecting ${displayName}...`, async () => {
39215
- await disconnectConnector(selectedType);
39216
- }, {
39217
- successMessage: `${displayName} disconnected`,
39218
- errorMessage: `Failed to disconnect ${displayName}`
39219
- });
39220
- return { outroMessage: `Successfully disconnected ${theme.styles.bold(displayName)}` };
39221
- }
39222
- const connectorsRemoveCommand = new Command("connectors:remove").argument("[type]", "Integration type to remove (e.g., slack, notion)").description("Disconnect an OAuth integration").action(async (type) => {
39223
- await runCommand(() => removeConnectorCommand(type), {
39224
- requireAuth: true,
39225
- requireAppConfig: true
39226
- });
39227
- });
39228
-
39229
38898
  //#endregion
39230
38899
  //#region package.json
39231
- var version = "0.0.15";
38900
+ var version = "0.0.16";
39232
38901
 
39233
38902
  //#endregion
39234
38903
  //#region src/cli/index.ts
@@ -39245,9 +38914,6 @@ program.addCommand(linkCommand);
39245
38914
  program.addCommand(entitiesPushCommand);
39246
38915
  program.addCommand(functionsDeployCommand);
39247
38916
  program.addCommand(siteDeployCommand);
39248
- program.addCommand(connectorsAddCommand);
39249
- program.addCommand(connectorsListCommand);
39250
- program.addCommand(connectorsRemoveCommand);
39251
38917
  program.parse();
39252
38918
 
39253
38919
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/cli",
3
- "version": "0.0.15-pr.99.e192f83",
3
+ "version": "0.0.16-pr.107.c96948c",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
6
  "main": "./dist/cli/index.js",