@base44-preview/cli 0.0.15-pr.98.72adf3c → 0.0.15-pr.99.05b68cd
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/dist/cli/index.js +425 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4547,6 +4547,7 @@ const string$1 = (params) => {
|
|
|
4547
4547
|
};
|
|
4548
4548
|
const integer = /^-?\d+$/;
|
|
4549
4549
|
const number$1 = /^-?\d+(?:\.\d+)?$/;
|
|
4550
|
+
const boolean$1 = /^(?:true|false)$/i;
|
|
4550
4551
|
const lowercase = /^[^A-Z]*$/;
|
|
4551
4552
|
const uppercase = /^[^a-z]*$/;
|
|
4552
4553
|
|
|
@@ -5325,6 +5326,24 @@ const $ZodNumberFormat = /* @__PURE__ */ $constructor("$ZodNumberFormat", (inst,
|
|
|
5325
5326
|
$ZodCheckNumberFormat.init(inst, def);
|
|
5326
5327
|
$ZodNumber.init(inst, def);
|
|
5327
5328
|
});
|
|
5329
|
+
const $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
|
|
5330
|
+
$ZodType.init(inst, def);
|
|
5331
|
+
inst._zod.pattern = boolean$1;
|
|
5332
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
5333
|
+
if (def.coerce) try {
|
|
5334
|
+
payload.value = Boolean(payload.value);
|
|
5335
|
+
} catch (_$2) {}
|
|
5336
|
+
const input = payload.value;
|
|
5337
|
+
if (typeof input === "boolean") return payload;
|
|
5338
|
+
payload.issues.push({
|
|
5339
|
+
expected: "boolean",
|
|
5340
|
+
code: "invalid_type",
|
|
5341
|
+
input,
|
|
5342
|
+
inst
|
|
5343
|
+
});
|
|
5344
|
+
return payload;
|
|
5345
|
+
};
|
|
5346
|
+
});
|
|
5328
5347
|
const $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
5329
5348
|
$ZodType.init(inst, def);
|
|
5330
5349
|
inst._zod.parse = (payload) => payload;
|
|
@@ -6379,6 +6398,13 @@ function _int(Class, params) {
|
|
|
6379
6398
|
});
|
|
6380
6399
|
}
|
|
6381
6400
|
/* @__NO_SIDE_EFFECTS__ */
|
|
6401
|
+
function _boolean(Class, params) {
|
|
6402
|
+
return new Class({
|
|
6403
|
+
type: "boolean",
|
|
6404
|
+
...normalizeParams(params)
|
|
6405
|
+
});
|
|
6406
|
+
}
|
|
6407
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
6382
6408
|
function _unknown(Class) {
|
|
6383
6409
|
return new Class({ type: "unknown" });
|
|
6384
6410
|
}
|
|
@@ -6949,6 +6975,9 @@ const numberProcessor = (schema, ctx, _json, _params) => {
|
|
|
6949
6975
|
}
|
|
6950
6976
|
if (typeof multipleOf === "number") json.multipleOf = multipleOf;
|
|
6951
6977
|
};
|
|
6978
|
+
const booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
6979
|
+
json.type = "boolean";
|
|
6980
|
+
};
|
|
6952
6981
|
const neverProcessor = (_schema, _ctx, json, _params) => {
|
|
6953
6982
|
json.not = {};
|
|
6954
6983
|
};
|
|
@@ -7472,6 +7501,14 @@ const ZodNumberFormat = /* @__PURE__ */ $constructor("ZodNumberFormat", (inst, d
|
|
|
7472
7501
|
function int(params) {
|
|
7473
7502
|
return _int(ZodNumberFormat, params);
|
|
7474
7503
|
}
|
|
7504
|
+
const ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
7505
|
+
$ZodBoolean.init(inst, def);
|
|
7506
|
+
ZodType.init(inst, def);
|
|
7507
|
+
inst._zod.processJSONSchema = (ctx, json, params) => booleanProcessor(inst, ctx, json, params);
|
|
7508
|
+
});
|
|
7509
|
+
function boolean(params) {
|
|
7510
|
+
return _boolean(ZodBoolean, params);
|
|
7511
|
+
}
|
|
7475
7512
|
const ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
7476
7513
|
$ZodUnknown.init(inst, def);
|
|
7477
7514
|
ZodType.init(inst, def);
|
|
@@ -7863,6 +7900,19 @@ var AuthValidationError = class extends Error {
|
|
|
7863
7900
|
this.name = "AuthValidationError";
|
|
7864
7901
|
}
|
|
7865
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
|
+
};
|
|
7866
7916
|
|
|
7867
7917
|
//#endregion
|
|
7868
7918
|
//#region src/core/consts.ts
|
|
@@ -30955,7 +31005,10 @@ const theme = {
|
|
|
30955
31005
|
base44OrangeBackground: source_default.bgHex("#E86B3C"),
|
|
30956
31006
|
shinyOrange: source_default.hex("#FFD700"),
|
|
30957
31007
|
links: source_default.hex("#00D4FF"),
|
|
30958
|
-
white: source_default.white
|
|
31008
|
+
white: source_default.white,
|
|
31009
|
+
success: source_default.green,
|
|
31010
|
+
warning: source_default.yellow,
|
|
31011
|
+
error: source_default.red
|
|
30959
31012
|
},
|
|
30960
31013
|
styles: {
|
|
30961
31014
|
header: source_default.dim,
|
|
@@ -38789,6 +38842,374 @@ const siteDeployCommand = new Command("site").description("Manage site deploymen
|
|
|
38789
38842
|
await runCommand(() => deployAction(options), { requireAuth: true });
|
|
38790
38843
|
}));
|
|
38791
38844
|
|
|
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
|
+
}).transform((data) => ({
|
|
38869
|
+
status: data.status,
|
|
38870
|
+
accountEmail: data.account_email,
|
|
38871
|
+
error: data.error
|
|
38872
|
+
}));
|
|
38873
|
+
/**
|
|
38874
|
+
* A connected integration from the list endpoint
|
|
38875
|
+
*/
|
|
38876
|
+
const ConnectorSchema = object({
|
|
38877
|
+
integration_type: string(),
|
|
38878
|
+
status: string(),
|
|
38879
|
+
connected_at: string().optional(),
|
|
38880
|
+
account_info: object({
|
|
38881
|
+
email: string().optional(),
|
|
38882
|
+
name: string().optional()
|
|
38883
|
+
}).optional()
|
|
38884
|
+
}).transform((data) => ({
|
|
38885
|
+
integrationType: data.integration_type,
|
|
38886
|
+
status: data.status,
|
|
38887
|
+
connectedAt: data.connected_at,
|
|
38888
|
+
accountInfo: data.account_info
|
|
38889
|
+
}));
|
|
38890
|
+
/**
|
|
38891
|
+
* Response from GET /api/apps/{app_id}/external-auth/list
|
|
38892
|
+
*/
|
|
38893
|
+
const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
|
|
38894
|
+
/**
|
|
38895
|
+
* Generic API error response
|
|
38896
|
+
*/
|
|
38897
|
+
const ApiErrorSchema = object({
|
|
38898
|
+
error: string(),
|
|
38899
|
+
detail: string().optional()
|
|
38900
|
+
});
|
|
38901
|
+
|
|
38902
|
+
//#endregion
|
|
38903
|
+
//#region src/core/connectors/api.ts
|
|
38904
|
+
/**
|
|
38905
|
+
* Initiates OAuth flow for a connector integration.
|
|
38906
|
+
* Returns a redirect URL to open in the browser.
|
|
38907
|
+
*/
|
|
38908
|
+
async function initiateOAuth(integrationType, scopes = null) {
|
|
38909
|
+
const response = await getAppClient().post("external-auth/initiate", {
|
|
38910
|
+
json: {
|
|
38911
|
+
integration_type: integrationType,
|
|
38912
|
+
scopes
|
|
38913
|
+
},
|
|
38914
|
+
throwHttpErrors: false
|
|
38915
|
+
});
|
|
38916
|
+
const json = await response.json();
|
|
38917
|
+
if (!response.ok) {
|
|
38918
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
38919
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
38920
|
+
throw new ConnectorApiError(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
|
|
38921
|
+
}
|
|
38922
|
+
const result = InitiateResponseSchema.safeParse(json);
|
|
38923
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid initiate response from server: ${result.error.message}`);
|
|
38924
|
+
return result.data;
|
|
38925
|
+
}
|
|
38926
|
+
/**
|
|
38927
|
+
* Checks the status of an OAuth connection attempt.
|
|
38928
|
+
*/
|
|
38929
|
+
async function checkOAuthStatus(integrationType, connectionId) {
|
|
38930
|
+
const response = await getAppClient().get("external-auth/status", {
|
|
38931
|
+
searchParams: {
|
|
38932
|
+
integration_type: integrationType,
|
|
38933
|
+
connection_id: connectionId
|
|
38934
|
+
},
|
|
38935
|
+
throwHttpErrors: false
|
|
38936
|
+
});
|
|
38937
|
+
const json = await response.json();
|
|
38938
|
+
if (!response.ok) {
|
|
38939
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
38940
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
38941
|
+
throw new ConnectorApiError(`Failed to check OAuth status: ${response.status} ${response.statusText}`);
|
|
38942
|
+
}
|
|
38943
|
+
const result = StatusResponseSchema.safeParse(json);
|
|
38944
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid status response from server: ${result.error.message}`);
|
|
38945
|
+
return result.data;
|
|
38946
|
+
}
|
|
38947
|
+
/**
|
|
38948
|
+
* Lists all connected integrations for the current app.
|
|
38949
|
+
*/
|
|
38950
|
+
async function listConnectors() {
|
|
38951
|
+
const response = await getAppClient().get("external-auth/list", { throwHttpErrors: false });
|
|
38952
|
+
const json = await response.json();
|
|
38953
|
+
if (!response.ok) {
|
|
38954
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
38955
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
38956
|
+
throw new ConnectorApiError(`Failed to list connectors: ${response.status} ${response.statusText}`);
|
|
38957
|
+
}
|
|
38958
|
+
const result = ListResponseSchema.safeParse(json);
|
|
38959
|
+
if (!result.success) throw new ConnectorValidationError(`Invalid list response from server: ${result.error.message}`);
|
|
38960
|
+
return result.data.integrations;
|
|
38961
|
+
}
|
|
38962
|
+
/**
|
|
38963
|
+
* Disconnects (soft delete) a connector integration.
|
|
38964
|
+
*/
|
|
38965
|
+
async function disconnectConnector(integrationType) {
|
|
38966
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}`, { throwHttpErrors: false });
|
|
38967
|
+
if (!response.ok) {
|
|
38968
|
+
const json = await response.json();
|
|
38969
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
38970
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
38971
|
+
throw new ConnectorApiError(`Failed to disconnect connector: ${response.status} ${response.statusText}`);
|
|
38972
|
+
}
|
|
38973
|
+
}
|
|
38974
|
+
/**
|
|
38975
|
+
* Removes (hard delete) a connector integration.
|
|
38976
|
+
* This permanently removes the connector and cannot be undone.
|
|
38977
|
+
*/
|
|
38978
|
+
async function removeConnector(integrationType) {
|
|
38979
|
+
const response = await getAppClient().delete(`external-auth/integrations/${integrationType}/remove`, { throwHttpErrors: false });
|
|
38980
|
+
if (!response.ok) {
|
|
38981
|
+
const json = await response.json();
|
|
38982
|
+
const errorResult = ApiErrorSchema.safeParse(json);
|
|
38983
|
+
if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
|
|
38984
|
+
throw new ConnectorApiError(`Failed to remove connector: ${response.status} ${response.statusText}`);
|
|
38985
|
+
}
|
|
38986
|
+
}
|
|
38987
|
+
|
|
38988
|
+
//#endregion
|
|
38989
|
+
//#region src/core/connectors/constants.ts
|
|
38990
|
+
/**
|
|
38991
|
+
* Supported OAuth connector integrations.
|
|
38992
|
+
* Based on apper/backend/app/external_auth/models/constants.py
|
|
38993
|
+
*/
|
|
38994
|
+
const SUPPORTED_INTEGRATIONS = [
|
|
38995
|
+
"googlecalendar",
|
|
38996
|
+
"googledrive",
|
|
38997
|
+
"gmail",
|
|
38998
|
+
"googlesheets",
|
|
38999
|
+
"googledocs",
|
|
39000
|
+
"googleslides",
|
|
39001
|
+
"slack",
|
|
39002
|
+
"notion",
|
|
39003
|
+
"salesforce",
|
|
39004
|
+
"hubspot",
|
|
39005
|
+
"linkedin",
|
|
39006
|
+
"tiktok"
|
|
39007
|
+
];
|
|
39008
|
+
/**
|
|
39009
|
+
* Display names for integrations (for CLI output)
|
|
39010
|
+
*/
|
|
39011
|
+
const INTEGRATION_DISPLAY_NAMES = {
|
|
39012
|
+
googlecalendar: "Google Calendar",
|
|
39013
|
+
googledrive: "Google Drive",
|
|
39014
|
+
gmail: "Gmail",
|
|
39015
|
+
googlesheets: "Google Sheets",
|
|
39016
|
+
googledocs: "Google Docs",
|
|
39017
|
+
googleslides: "Google Slides",
|
|
39018
|
+
slack: "Slack",
|
|
39019
|
+
notion: "Notion",
|
|
39020
|
+
salesforce: "Salesforce",
|
|
39021
|
+
hubspot: "HubSpot",
|
|
39022
|
+
linkedin: "LinkedIn",
|
|
39023
|
+
tiktok: "TikTok"
|
|
39024
|
+
};
|
|
39025
|
+
function isValidIntegration(type) {
|
|
39026
|
+
return SUPPORTED_INTEGRATIONS.includes(type);
|
|
39027
|
+
}
|
|
39028
|
+
function getIntegrationDisplayName(type) {
|
|
39029
|
+
if (isValidIntegration(type)) return INTEGRATION_DISPLAY_NAMES[type];
|
|
39030
|
+
return type;
|
|
39031
|
+
}
|
|
39032
|
+
|
|
39033
|
+
//#endregion
|
|
39034
|
+
//#region src/cli/commands/connectors/add.ts
|
|
39035
|
+
const POLL_INTERVAL_MS = 2e3;
|
|
39036
|
+
const POLL_TIMEOUT_MS = 300 * 1e3;
|
|
39037
|
+
async function promptForIntegrationType() {
|
|
39038
|
+
const selected = await ve({
|
|
39039
|
+
message: "Select an integration to connect:",
|
|
39040
|
+
options: SUPPORTED_INTEGRATIONS.map((type) => ({
|
|
39041
|
+
value: type,
|
|
39042
|
+
label: getIntegrationDisplayName(type)
|
|
39043
|
+
}))
|
|
39044
|
+
});
|
|
39045
|
+
if (pD(selected)) return null;
|
|
39046
|
+
return selected;
|
|
39047
|
+
}
|
|
39048
|
+
async function waitForOAuthCompletion(integrationType, connectionId) {
|
|
39049
|
+
let accountEmail;
|
|
39050
|
+
let error;
|
|
39051
|
+
try {
|
|
39052
|
+
await runTask("Waiting for authorization...", async (updateMessage) => {
|
|
39053
|
+
await pWaitFor(async () => {
|
|
39054
|
+
const status = await checkOAuthStatus(integrationType, connectionId);
|
|
39055
|
+
if (status.status === "ACTIVE") {
|
|
39056
|
+
accountEmail = status.accountEmail;
|
|
39057
|
+
return true;
|
|
39058
|
+
}
|
|
39059
|
+
if (status.status === "FAILED") {
|
|
39060
|
+
error = status.error || "Authorization failed";
|
|
39061
|
+
throw new Error(error);
|
|
39062
|
+
}
|
|
39063
|
+
updateMessage("Waiting for authorization in browser...");
|
|
39064
|
+
return false;
|
|
39065
|
+
}, {
|
|
39066
|
+
interval: POLL_INTERVAL_MS,
|
|
39067
|
+
timeout: POLL_TIMEOUT_MS
|
|
39068
|
+
});
|
|
39069
|
+
}, {
|
|
39070
|
+
successMessage: "Authorization completed!",
|
|
39071
|
+
errorMessage: "Authorization failed"
|
|
39072
|
+
});
|
|
39073
|
+
return {
|
|
39074
|
+
success: true,
|
|
39075
|
+
accountEmail
|
|
39076
|
+
};
|
|
39077
|
+
} catch (err) {
|
|
39078
|
+
if (err instanceof Error && err.message.includes("timed out")) return {
|
|
39079
|
+
success: false,
|
|
39080
|
+
error: "Authorization timed out. Please try again."
|
|
39081
|
+
};
|
|
39082
|
+
return {
|
|
39083
|
+
success: false,
|
|
39084
|
+
error: error || (err instanceof Error ? err.message : "Unknown error")
|
|
39085
|
+
};
|
|
39086
|
+
}
|
|
39087
|
+
}
|
|
39088
|
+
async function addConnector(integrationType) {
|
|
39089
|
+
let selectedType;
|
|
39090
|
+
if (!integrationType) {
|
|
39091
|
+
const prompted = await promptForIntegrationType();
|
|
39092
|
+
if (!prompted) return { outroMessage: "Cancelled" };
|
|
39093
|
+
selectedType = prompted;
|
|
39094
|
+
} else {
|
|
39095
|
+
if (!isValidIntegration(integrationType)) {
|
|
39096
|
+
const supportedList = SUPPORTED_INTEGRATIONS.join(", ");
|
|
39097
|
+
throw new Error(`Unsupported connector: ${integrationType}\nSupported connectors: ${supportedList}`);
|
|
39098
|
+
}
|
|
39099
|
+
selectedType = integrationType;
|
|
39100
|
+
}
|
|
39101
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39102
|
+
const initiateResponse = await runTask(`Initiating ${displayName} connection...`, async () => {
|
|
39103
|
+
return await initiateOAuth(selectedType);
|
|
39104
|
+
}, {
|
|
39105
|
+
successMessage: `${displayName} OAuth initiated`,
|
|
39106
|
+
errorMessage: `Failed to initiate ${displayName} connection`
|
|
39107
|
+
});
|
|
39108
|
+
if (initiateResponse.already_authorized) return { outroMessage: `Already connected to ${theme.styles.bold(displayName)}` };
|
|
39109
|
+
if (initiateResponse.error === "different_user" && initiateResponse.other_user_email) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.other_user_email}`);
|
|
39110
|
+
if (!initiateResponse.redirect_url || !initiateResponse.connection_id) throw new Error("Invalid response from server: missing redirect URL or connection ID");
|
|
39111
|
+
M.info(`Opening browser for ${displayName} authorization...`);
|
|
39112
|
+
await open_default(initiateResponse.redirect_url);
|
|
39113
|
+
const result = await waitForOAuthCompletion(selectedType, initiateResponse.connection_id);
|
|
39114
|
+
if (!result.success) throw new Error(result.error || "Authorization failed");
|
|
39115
|
+
const accountInfo = result.accountEmail ? ` as ${theme.styles.bold(result.accountEmail)}` : "";
|
|
39116
|
+
return { outroMessage: `Successfully connected to ${theme.styles.bold(displayName)}${accountInfo}` };
|
|
39117
|
+
}
|
|
39118
|
+
const connectorsAddCommand = new Command("connectors:add").argument("[type]", "Integration type (e.g., slack, notion, googlecalendar)").description("Connect an OAuth integration").action(async (type) => {
|
|
39119
|
+
await runCommand(() => addConnector(type), {
|
|
39120
|
+
requireAuth: true,
|
|
39121
|
+
requireAppConfig: true
|
|
39122
|
+
});
|
|
39123
|
+
});
|
|
39124
|
+
|
|
39125
|
+
//#endregion
|
|
39126
|
+
//#region src/cli/commands/connectors/list.ts
|
|
39127
|
+
function formatConnectorLine(connector) {
|
|
39128
|
+
const name$1 = getIntegrationDisplayName(connector.integrationType);
|
|
39129
|
+
const account = connector.accountInfo?.email || connector.accountInfo?.name;
|
|
39130
|
+
const status = connector.status.toLowerCase();
|
|
39131
|
+
return `${status === "active" ? theme.colors.success("●") : theme.colors.error("○")} ${name$1}${account ? ` - ${account}` : ""}${status !== "active" ? theme.styles.dim(` (${status})`) : ""}`;
|
|
39132
|
+
}
|
|
39133
|
+
async function listConnectorsCommand() {
|
|
39134
|
+
const connectors = await runTask("Fetching connectors...", async () => {
|
|
39135
|
+
return await listConnectors();
|
|
39136
|
+
}, {
|
|
39137
|
+
successMessage: "Connectors loaded",
|
|
39138
|
+
errorMessage: "Failed to fetch connectors"
|
|
39139
|
+
});
|
|
39140
|
+
if (connectors.length === 0) {
|
|
39141
|
+
M.info("No connectors configured for this app.");
|
|
39142
|
+
M.info(`Run ${theme.styles.bold("base44 connectors:add")} to connect an integration.`);
|
|
39143
|
+
return { outroMessage: "" };
|
|
39144
|
+
}
|
|
39145
|
+
console.log();
|
|
39146
|
+
for (const connector of connectors) console.log(formatConnectorLine(connector));
|
|
39147
|
+
console.log();
|
|
39148
|
+
return { outroMessage: `${connectors.length} connector${connectors.length === 1 ? "" : "s"} configured` };
|
|
39149
|
+
}
|
|
39150
|
+
const connectorsListCommand = new Command("connectors:list").description("List all connected OAuth integrations").action(async () => {
|
|
39151
|
+
await runCommand(listConnectorsCommand, {
|
|
39152
|
+
requireAuth: true,
|
|
39153
|
+
requireAppConfig: true
|
|
39154
|
+
});
|
|
39155
|
+
});
|
|
39156
|
+
|
|
39157
|
+
//#endregion
|
|
39158
|
+
//#region src/cli/commands/connectors/remove.ts
|
|
39159
|
+
async function promptForConnectorToRemove(connectors) {
|
|
39160
|
+
const selected = await ve({
|
|
39161
|
+
message: "Select a connector to remove:",
|
|
39162
|
+
options: connectors.map((c$1) => ({
|
|
39163
|
+
value: c$1.integrationType,
|
|
39164
|
+
label: `${getIntegrationDisplayName(c$1.integrationType)}${c$1.accountInfo?.email ? ` (${c$1.accountInfo.email})` : ""}`
|
|
39165
|
+
}))
|
|
39166
|
+
});
|
|
39167
|
+
if (pD(selected)) return null;
|
|
39168
|
+
return selected;
|
|
39169
|
+
}
|
|
39170
|
+
async function removeConnectorCommand(integrationType, options = {}) {
|
|
39171
|
+
const isHardDelete = options.hard === true;
|
|
39172
|
+
const connectors = await runTask("Fetching connectors...", async () => {
|
|
39173
|
+
return await listConnectors();
|
|
39174
|
+
}, {
|
|
39175
|
+
successMessage: "Connectors loaded",
|
|
39176
|
+
errorMessage: "Failed to fetch connectors"
|
|
39177
|
+
});
|
|
39178
|
+
if (connectors.length === 0) return { outroMessage: "No connectors to remove" };
|
|
39179
|
+
let selectedType;
|
|
39180
|
+
if (!integrationType) {
|
|
39181
|
+
const prompted = await promptForConnectorToRemove(connectors);
|
|
39182
|
+
if (!prompted) return { outroMessage: "Cancelled" };
|
|
39183
|
+
selectedType = prompted;
|
|
39184
|
+
} else {
|
|
39185
|
+
if (!isValidIntegration(integrationType)) throw new Error(`Invalid connector type: ${integrationType}`);
|
|
39186
|
+
if (!connectors.some((c$1) => c$1.integrationType === integrationType)) throw new Error(`No ${getIntegrationDisplayName(integrationType)} connector found for this app`);
|
|
39187
|
+
selectedType = integrationType;
|
|
39188
|
+
}
|
|
39189
|
+
const displayName = getIntegrationDisplayName(selectedType);
|
|
39190
|
+
const connector = connectors.find((c$1) => c$1.integrationType === selectedType);
|
|
39191
|
+
const accountInfo = connector?.accountInfo?.email ? ` (${connector.accountInfo.email})` : "";
|
|
39192
|
+
const shouldRemove = await ye({
|
|
39193
|
+
message: `${isHardDelete ? "Permanently remove" : "Disconnect"} ${displayName}${accountInfo}?`,
|
|
39194
|
+
initialValue: false
|
|
39195
|
+
});
|
|
39196
|
+
if (pD(shouldRemove) || !shouldRemove) return { outroMessage: "Cancelled" };
|
|
39197
|
+
await runTask(isHardDelete ? `Removing ${displayName}...` : `Disconnecting ${displayName}...`, async () => {
|
|
39198
|
+
if (isHardDelete) await removeConnector(selectedType);
|
|
39199
|
+
else await disconnectConnector(selectedType);
|
|
39200
|
+
}, {
|
|
39201
|
+
successMessage: isHardDelete ? `${displayName} removed` : `${displayName} disconnected`,
|
|
39202
|
+
errorMessage: isHardDelete ? `Failed to remove ${displayName}` : `Failed to disconnect ${displayName}`
|
|
39203
|
+
});
|
|
39204
|
+
return { outroMessage: `Successfully ${isHardDelete ? "removed" : "disconnected"} ${theme.styles.bold(displayName)}` };
|
|
39205
|
+
}
|
|
39206
|
+
const connectorsRemoveCommand = new Command("connectors:remove").argument("[type]", "Integration type to remove (e.g., slack, notion)").option("--hard", "Permanently remove the connector (cannot be undone)").description("Disconnect an OAuth integration").action(async (type, options) => {
|
|
39207
|
+
await runCommand(() => removeConnectorCommand(type, options), {
|
|
39208
|
+
requireAuth: true,
|
|
39209
|
+
requireAppConfig: true
|
|
39210
|
+
});
|
|
39211
|
+
});
|
|
39212
|
+
|
|
38792
39213
|
//#endregion
|
|
38793
39214
|
//#region package.json
|
|
38794
39215
|
var version = "0.0.15";
|
|
@@ -38808,6 +39229,9 @@ program.addCommand(linkCommand);
|
|
|
38808
39229
|
program.addCommand(entitiesPushCommand);
|
|
38809
39230
|
program.addCommand(functionsDeployCommand);
|
|
38810
39231
|
program.addCommand(siteDeployCommand);
|
|
39232
|
+
program.addCommand(connectorsAddCommand);
|
|
39233
|
+
program.addCommand(connectorsListCommand);
|
|
39234
|
+
program.addCommand(connectorsRemoveCommand);
|
|
38811
39235
|
program.parse();
|
|
38812
39236
|
|
|
38813
39237
|
//#endregion
|
package/package.json
CHANGED