@base44-preview/cli 0.0.25-pr.104.089a20e → 0.0.25-pr.104.a8520b5

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.
Files changed (2) hide show
  1. package/dist/index.js +106 -49
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8038,6 +8038,19 @@ var AuthValidationError = class extends Error {
8038
8038
  this.name = "AuthValidationError";
8039
8039
  }
8040
8040
  };
8041
+ var ConnectorApiError = class extends Error {
8042
+ constructor(message, cause) {
8043
+ super(message);
8044
+ this.cause = cause;
8045
+ this.name = "ConnectorApiError";
8046
+ }
8047
+ };
8048
+ var ConnectorValidationError = class extends Error {
8049
+ constructor(message) {
8050
+ super(message);
8051
+ this.name = "ConnectorValidationError";
8052
+ }
8053
+ };
8041
8054
 
8042
8055
  //#endregion
8043
8056
  //#region src/core/consts.ts
@@ -30793,7 +30806,7 @@ function getAppClient() {
30793
30806
 
30794
30807
  //#endregion
30795
30808
  //#region src/core/clients/schemas.ts
30796
- const ApiErrorSchema = object({
30809
+ const ApiErrorSchema$1 = object({
30797
30810
  error_type: string().optional(),
30798
30811
  message: union([string(), record(string(), unknown())]).optional(),
30799
30812
  detail: union([
@@ -39278,13 +39291,7 @@ const InitiateResponseSchema = object({
39278
39291
  already_authorized: boolean().nullish(),
39279
39292
  other_user_email: string().nullish(),
39280
39293
  error: string().nullish()
39281
- }).transform((data) => ({
39282
- redirectUrl: data.redirect_url,
39283
- connectionId: data.connection_id,
39284
- alreadyAuthorized: data.already_authorized,
39285
- otherUserEmail: data.other_user_email,
39286
- error: data.error
39287
- }));
39294
+ });
39288
39295
  /**
39289
39296
  * Response from GET /api/apps/{app_id}/external-auth/status
39290
39297
  */
@@ -39322,6 +39329,13 @@ const ConnectorSchema = object({
39322
39329
  * Response from GET /api/apps/{app_id}/external-auth/list
39323
39330
  */
39324
39331
  const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
39332
+ /**
39333
+ * Generic API error response
39334
+ */
39335
+ const ApiErrorSchema = object({
39336
+ error: string(),
39337
+ detail: string().nullish()
39338
+ });
39325
39339
 
39326
39340
  //#endregion
39327
39341
  //#region src/core/connectors/api.ts
@@ -39330,45 +39344,92 @@ const ListResponseSchema = object({ integrations: array(ConnectorSchema) });
39330
39344
  * Returns a redirect URL to open in the browser.
39331
39345
  */
39332
39346
  async function initiateOAuth(integrationType, scopes = null) {
39333
- const json = await (await getAppClient().post("external-auth/initiate", { json: {
39334
- integration_type: integrationType,
39335
- scopes
39336
- } })).json();
39337
- return InitiateResponseSchema.parse(json);
39347
+ const response = await getAppClient().post("external-auth/initiate", {
39348
+ json: {
39349
+ integration_type: integrationType,
39350
+ scopes
39351
+ },
39352
+ throwHttpErrors: false
39353
+ });
39354
+ const json = await response.json();
39355
+ if (!response.ok) {
39356
+ const errorResult = ApiErrorSchema.safeParse(json);
39357
+ if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
39358
+ throw new ConnectorApiError(`Failed to initiate OAuth: ${response.status} ${response.statusText}`);
39359
+ }
39360
+ const result = InitiateResponseSchema.safeParse(json);
39361
+ if (!result.success) throw new ConnectorValidationError(`Invalid initiate response from server: ${result.error.message}`);
39362
+ return result.data;
39338
39363
  }
39339
39364
  /**
39340
39365
  * Checks the status of an OAuth connection attempt.
39341
39366
  */
39342
39367
  async function checkOAuthStatus(integrationType, connectionId) {
39343
- const json = await (await getAppClient().get("external-auth/status", { searchParams: {
39344
- integration_type: integrationType,
39345
- connection_id: connectionId
39346
- } })).json();
39347
- return StatusResponseSchema.parse(json);
39368
+ const response = await getAppClient().get("external-auth/status", {
39369
+ searchParams: {
39370
+ integration_type: integrationType,
39371
+ connection_id: connectionId
39372
+ },
39373
+ throwHttpErrors: false
39374
+ });
39375
+ const json = await response.json();
39376
+ if (!response.ok) {
39377
+ const errorResult = ApiErrorSchema.safeParse(json);
39378
+ if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
39379
+ throw new ConnectorApiError(`Failed to check OAuth status: ${response.status} ${response.statusText}`);
39380
+ }
39381
+ const result = StatusResponseSchema.safeParse(json);
39382
+ if (!result.success) throw new ConnectorValidationError(`Invalid status response from server: ${result.error.message}`);
39383
+ return result.data;
39348
39384
  }
39349
39385
  /**
39350
39386
  * Lists all connected integrations for the current app.
39351
39387
  */
39352
39388
  async function listConnectors() {
39353
- const json = await (await getAppClient().get("external-auth/list")).json();
39354
- return ListResponseSchema.parse(json).integrations;
39389
+ const response = await getAppClient().get("external-auth/list", { throwHttpErrors: false });
39390
+ const json = await response.json();
39391
+ if (!response.ok) {
39392
+ const errorResult = ApiErrorSchema.safeParse(json);
39393
+ if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
39394
+ throw new ConnectorApiError(`Failed to list connectors: ${response.status} ${response.statusText}`);
39395
+ }
39396
+ const result = ListResponseSchema.safeParse(json);
39397
+ if (!result.success) throw new ConnectorValidationError(`Invalid list response from server: ${result.error.message}`);
39398
+ return result.data.integrations;
39355
39399
  }
39356
39400
  /**
39357
39401
  * Disconnects (soft delete) a connector integration.
39358
39402
  */
39359
39403
  async function disconnectConnector(integrationType) {
39360
- await getAppClient().delete(`external-auth/integrations/${integrationType}`);
39404
+ const response = await getAppClient().delete(`external-auth/integrations/${integrationType}`, { throwHttpErrors: false });
39405
+ if (!response.ok) {
39406
+ const json = await response.json();
39407
+ const errorResult = ApiErrorSchema.safeParse(json);
39408
+ if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
39409
+ throw new ConnectorApiError(`Failed to disconnect connector: ${response.status} ${response.statusText}`);
39410
+ }
39361
39411
  }
39362
39412
  /**
39363
39413
  * Removes (hard delete) a connector integration.
39364
39414
  * This permanently removes the connector and cannot be undone.
39365
39415
  */
39366
39416
  async function removeConnector(integrationType) {
39367
- await getAppClient().delete(`external-auth/integrations/${integrationType}/remove`);
39417
+ const response = await getAppClient().delete(`external-auth/integrations/${integrationType}/remove`, { throwHttpErrors: false });
39418
+ if (!response.ok) {
39419
+ const json = await response.json();
39420
+ const errorResult = ApiErrorSchema.safeParse(json);
39421
+ if (errorResult.success) throw new ConnectorApiError(errorResult.data.error);
39422
+ throw new ConnectorApiError(`Failed to remove connector: ${response.status} ${response.statusText}`);
39423
+ }
39368
39424
  }
39369
39425
 
39370
39426
  //#endregion
39371
- //#region src/core/connectors/consts.ts
39427
+ //#region src/core/connectors/constants.ts
39428
+ /**
39429
+ * OAuth polling configuration
39430
+ */
39431
+ const OAUTH_POLL_INTERVAL_MS = 2e3;
39432
+ const OAUTH_POLL_TIMEOUT_MS = 300 * 1e3;
39372
39433
  /**
39373
39434
  * Supported OAuth connector integrations.
39374
39435
  * Based on apper/backend/app/external_auth/models/constants.py
@@ -39408,13 +39469,12 @@ function isValidIntegration(type) {
39408
39469
  return SUPPORTED_INTEGRATIONS.includes(type);
39409
39470
  }
39410
39471
  function getIntegrationDisplayName(type) {
39411
- return INTEGRATION_DISPLAY_NAMES[type] ?? type;
39472
+ if (isValidIntegration(type)) return INTEGRATION_DISPLAY_NAMES[type];
39473
+ return type;
39412
39474
  }
39413
39475
 
39414
39476
  //#endregion
39415
- //#region src/cli/commands/connectors/utils.ts
39416
- const OAUTH_POLL_INTERVAL_MS = 2e3;
39417
- const OAUTH_POLL_TIMEOUT_MS = 300 * 1e3;
39477
+ //#region src/core/connectors/oauth.ts
39418
39478
  /**
39419
39479
  * Polls for OAuth completion status.
39420
39480
  * Returns when status becomes ACTIVE or FAILED, or times out.
@@ -39454,24 +39514,22 @@ async function waitForOAuthCompletion(integrationType, connectionId, options) {
39454
39514
  };
39455
39515
  }
39456
39516
  }
39457
- /**
39458
- * Asserts that a string is a valid integration type, throwing if not.
39459
- */
39460
- function assertValidIntegrationType(type, supportedIntegrations) {
39461
- if (!supportedIntegrations.includes(type)) {
39462
- const supportedList = supportedIntegrations.join(", ");
39463
- throw new Error(`Unsupported connector: ${type}\nSupported connectors: ${supportedList}`);
39464
- }
39465
- }
39466
39517
 
39467
39518
  //#endregion
39468
39519
  //#region src/cli/commands/connectors/add.ts
39520
+ function validateIntegrationType(type) {
39521
+ if (!isValidIntegration(type)) {
39522
+ const supportedList = SUPPORTED_INTEGRATIONS.join(", ");
39523
+ throw new Error(`Unsupported connector: ${type}\nSupported connectors: ${supportedList}`);
39524
+ }
39525
+ return type;
39526
+ }
39469
39527
  async function promptForIntegrationType() {
39470
39528
  const selected = await ve({
39471
39529
  message: "Select an integration to connect:",
39472
- options: Object.entries(INTEGRATION_DISPLAY_NAMES).map(([type, displayName]) => ({
39530
+ options: SUPPORTED_INTEGRATIONS.map((type) => ({
39473
39531
  value: type,
39474
- label: displayName
39532
+ label: getIntegrationDisplayName(type)
39475
39533
  }))
39476
39534
  });
39477
39535
  if (pD(selected)) {
@@ -39489,11 +39547,7 @@ async function pollForOAuthCompletion(integrationType, connectionId) {
39489
39547
  });
39490
39548
  }
39491
39549
  async function addConnector(integrationType) {
39492
- let selectedType;
39493
- if (integrationType) {
39494
- assertValidIntegrationType(integrationType, SUPPORTED_INTEGRATIONS);
39495
- selectedType = integrationType;
39496
- } else selectedType = await promptForIntegrationType();
39550
+ const selectedType = integrationType ? validateIntegrationType(integrationType) : await promptForIntegrationType();
39497
39551
  const displayName = getIntegrationDisplayName(selectedType);
39498
39552
  const initiateResponse = await runTask(`Initiating ${displayName} connection...`, async () => {
39499
39553
  return await initiateOAuth(selectedType);
@@ -39501,11 +39555,11 @@ async function addConnector(integrationType) {
39501
39555
  successMessage: `${displayName} OAuth initiated`,
39502
39556
  errorMessage: `Failed to initiate ${displayName} connection`
39503
39557
  });
39504
- if (initiateResponse.alreadyAuthorized) return { outroMessage: `Already connected to ${theme.styles.bold(displayName)}` };
39505
- if (initiateResponse.error === "different_user" && initiateResponse.otherUserEmail) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.otherUserEmail}`);
39506
- if (!initiateResponse.redirectUrl || !initiateResponse.connectionId) throw new Error("Invalid response from server: missing redirect URL or connection ID");
39507
- M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirectUrl)}`);
39508
- const result = await pollForOAuthCompletion(selectedType, initiateResponse.connectionId);
39558
+ if (initiateResponse.already_authorized) return { outroMessage: `Already connected to ${theme.styles.bold(displayName)}` };
39559
+ if (initiateResponse.error === "different_user" && initiateResponse.other_user_email) throw new Error(`This app is already connected to ${displayName} by ${initiateResponse.other_user_email}`);
39560
+ if (!initiateResponse.redirect_url || !initiateResponse.connection_id) throw new Error("Invalid response from server: missing redirect URL or connection ID");
39561
+ M.info(`Please authorize ${displayName} at:\n${theme.colors.links(initiateResponse.redirect_url)}`);
39562
+ const result = await pollForOAuthCompletion(selectedType, initiateResponse.connection_id);
39509
39563
  if (!result.success) throw new Error(result.error || "Authorization failed");
39510
39564
  const accountInfo = result.accountEmail ? ` as ${theme.styles.bold(result.accountEmail)}` : "";
39511
39565
  return { outroMessage: `Successfully connected to ${theme.styles.bold(displayName)}${accountInfo}` };
@@ -39561,7 +39615,10 @@ async function removeConnectorCommand(integrationType, options = {}) {
39561
39615
  const displayName = selectedConnector.displayName;
39562
39616
  const accountInfo = selectedConnector.accountEmail ? ` (${selectedConnector.accountEmail})` : "";
39563
39617
  if (!options.yes) {
39564
- const shouldRemove = await ye({ message: `${isHardDelete ? "Permanently remove" : "Remove"} ${displayName}${accountInfo}?` });
39618
+ const shouldRemove = await ye({
39619
+ message: `${isHardDelete ? "Permanently remove" : "Remove"} ${displayName}${accountInfo}?`,
39620
+ initialValue: false
39621
+ });
39565
39622
  if (pD(shouldRemove) || !shouldRemove) {
39566
39623
  xe("Operation cancelled.");
39567
39624
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/cli",
3
- "version": "0.0.25-pr.104.089a20e",
3
+ "version": "0.0.25-pr.104.a8520b5",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
6
  "bin": {